Salome HOME
Synchronize adm files
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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 "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 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 };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
128   ret.push_back(_nodal_connec);
129   ret.push_back(_nodal_connec_index);
130   return ret;
131 }
132
133 void MEDCouplingUMesh::updateTime() const
134 {
135   MEDCouplingPointSet::updateTime();
136   if(_nodal_connec)
137     {
138       updateTimeWith(*_nodal_connec);
139     }
140   if(_nodal_connec_index)
141     {
142       updateTimeWith(*_nodal_connec_index);
143     }
144 }
145
146 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
147 {
148 }
149
150 /*!
151  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
152  * then \a this mesh is most probably is writable, exchangeable and available for most
153  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
154  * this method to check that all is in order with \a this mesh.
155  *  \throw If the mesh dimension is not set.
156  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
157  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
158  *  \throw If the connectivity data array has more than one component.
159  *  \throw If the connectivity data array has a named component.
160  *  \throw If the connectivity index data array has more than one component.
161  *  \throw If the connectivity index data array has a named component.
162  */
163 void MEDCouplingUMesh::checkCoherency() const
164 {
165   if(_mesh_dim<-1)
166     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
167   if(_mesh_dim!=-1)
168     MEDCouplingPointSet::checkCoherency();
169   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
170     {
171       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
172         {
173           std::ostringstream message;
174           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
175           throw INTERP_KERNEL::Exception(message.str().c_str());
176         }
177     }
178   if(_nodal_connec)
179     {
180       if(_nodal_connec->getNumberOfComponents()!=1)
181         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
182       if(_nodal_connec->getInfoOnComponent(0)!="")
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
184     }
185   else
186     if(_mesh_dim!=-1)
187       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
188   if(_nodal_connec_index)
189     {
190       if(_nodal_connec_index->getNumberOfComponents()!=1)
191         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
192       if(_nodal_connec_index->getInfoOnComponent(0)!="")
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
194     }
195   else
196     if(_mesh_dim!=-1)
197       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
198 }
199
200 /*!
201  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
202  * then \a this mesh is most probably is writable, exchangeable and available for all
203  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
204  * method thoroughly checks the nodal connectivity.
205  *  \param [in] eps - a not used parameter.
206  *  \throw If the mesh dimension is not set.
207  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
208  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
209  *  \throw If the connectivity data array has more than one component.
210  *  \throw If the connectivity data array has a named component.
211  *  \throw If the connectivity index data array has more than one component.
212  *  \throw If the connectivity index data array has a named component.
213  *  \throw If number of nodes defining an element does not correspond to the type of element.
214  *  \throw If the nodal connectivity includes an invalid node id.
215  */
216 void MEDCouplingUMesh::checkCoherency1(double eps) const
217 {
218   checkCoherency();
219   if(_mesh_dim==-1)
220     return ;
221   int meshDim=getMeshDimension();
222   int nbOfNodes=getNumberOfNodes();
223   int nbOfCells=getNumberOfCells();
224   const int *ptr=_nodal_connec->getConstPointer();
225   const int *ptrI=_nodal_connec_index->getConstPointer();
226   for(int i=0;i<nbOfCells;i++)
227     {
228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
229       if((int)cm.getDimension()!=meshDim)
230         {
231           std::ostringstream oss;
232           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
233           throw INTERP_KERNEL::Exception(oss.str().c_str());
234         }
235       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
236       if(!cm.isDynamic())
237         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
238           {
239             std::ostringstream oss;
240             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
241             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
242             throw INTERP_KERNEL::Exception(oss.str().c_str());
243           }
244       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
245         {
246           int nodeId=*w;
247           if(nodeId>=0)
248             {
249               if(nodeId>=nbOfNodes)
250                 {
251                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
252                   throw INTERP_KERNEL::Exception(oss.str().c_str());
253                 }
254             }
255           else if(nodeId<-1)
256             {
257               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
258               throw INTERP_KERNEL::Exception(oss.str().c_str());
259             }
260           else
261             {
262               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
265                   throw INTERP_KERNEL::Exception(oss.str().c_str());
266                 }
267             }
268         }
269     }
270 }
271
272
273 /*!
274  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
275  * then \a this mesh is most probably is writable, exchangeable and available for all
276  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
277  *  \param [in] eps - a not used parameter.
278  *  \throw If the mesh dimension is not set.
279  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
280  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
281  *  \throw If the connectivity data array has more than one component.
282  *  \throw If the connectivity data array has a named component.
283  *  \throw If the connectivity index data array has more than one component.
284  *  \throw If the connectivity index data array has a named component.
285  *  \throw If number of nodes defining an element does not correspond to the type of element.
286  *  \throw If the nodal connectivity includes an invalid node id.
287  */
288 void MEDCouplingUMesh::checkCoherency2(double eps) const
289 {
290   checkCoherency1(eps);
291 }
292
293 /*!
294  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
295  * elements contained in the mesh. For more info on the mesh dimension see
296  * \ref MEDCouplingUMeshPage.
297  *  \param [in] meshDim - a new mesh dimension.
298  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
299  */
300 void MEDCouplingUMesh::setMeshDimension(int meshDim)
301 {
302   if(meshDim<-1 || meshDim>3)
303     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
304   _mesh_dim=meshDim;
305   declareAsNew();
306 }
307
308 /*!
309  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
310  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
311  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
312  *
313  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
314  *
315  *  \if ENABLE_EXAMPLES
316  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
317  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
318  *  \endif
319  */
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
321 {
322   if(nbOfCells<0)
323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324   if(_nodal_connec_index)
325     {
326       _nodal_connec_index->decrRef();
327     }
328   if(_nodal_connec)
329     {
330       _nodal_connec->decrRef();
331     }
332   _nodal_connec_index=DataArrayInt::New();
333   _nodal_connec_index->reserve(nbOfCells+1);
334   _nodal_connec_index->pushBackSilent(0);
335   _nodal_connec=DataArrayInt::New();
336   _nodal_connec->reserve(2*nbOfCells);
337   _types.clear();
338   declareAsNew();
339 }
340
341 /*!
342  * Appends a cell to the connectivity array. For deeper understanding what is
343  * happening see \ref MEDCouplingUMeshNodalConnectivity.
344  *  \param [in] type - type of cell to add.
345  *  \param [in] size - number of nodes constituting this cell.
346  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
347  * 
348  *  \if ENABLE_EXAMPLES
349  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
350  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
351  *  \endif
352  */
353 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
354 {
355   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
356   if(_nodal_connec_index==0)
357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
358   if((int)cm.getDimension()==_mesh_dim)
359     {
360       if(!cm.isDynamic())
361         if(size!=(int)cm.getNumberOfNodes())
362           {
363             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
364             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
365             throw INTERP_KERNEL::Exception(oss.str().c_str());
366           }
367       int idx=_nodal_connec_index->back();
368       int val=idx+size+1;
369       _nodal_connec_index->pushBackSilent(val);
370       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
371       _types.insert(type);
372     }
373   else
374     {
375       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
376       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
377       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
378       throw INTERP_KERNEL::Exception(oss.str().c_str());
379     }
380 }
381
382 /*!
383  * Compacts data arrays to release unused memory. This method is to be called after
384  * finishing cell insertion using \a this->insertNextCell().
385  * 
386  *  \if ENABLE_EXAMPLES
387  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
388  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
389  *  \endif
390  */
391 void MEDCouplingUMesh::finishInsertingCells()
392 {
393   _nodal_connec->pack();
394   _nodal_connec_index->pack();
395   _nodal_connec->declareAsNew();
396   _nodal_connec_index->declareAsNew();
397   updateTime();
398 }
399
400 /*!
401  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
402  * Useful for python users.
403  */
404 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
405 {
406   return new MEDCouplingUMeshCellIterator(this);
407 }
408
409 /*!
410  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
411  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
412  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
413  * Useful for python users.
414  */
415 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
416 {
417   if(!checkConsecutiveCellTypes())
418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
419   return new MEDCouplingUMeshCellByTypeEntry(this);
420 }
421
422 /*!
423  * Returns a set of all cell types available in \a this mesh.
424  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
425  * \warning this method does not throw any exception even if \a this is not defined.
426  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
427  */
428 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
429 {
430   return _types;
431 }
432
433 /*!
434  * This method returns the sorted list of geometric types in \a this.
435  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
436  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
437  *
438  * \throw if connectivity in \a this is not correctly defined.
439  *  
440  * \sa MEDCouplingMesh::getAllGeoTypes
441  */
442 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
443 {
444   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
445   checkConnectivityFullyDefined();
446   int nbOfCells(getNumberOfCells());
447   if(nbOfCells==0)
448     return ret;
449   if(getMeshLength()<1)
450     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
451   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
452   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
453   for(int i=1;i<nbOfCells;i++,ci++)
454     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
455       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
456   return ret;
457 }
458
459 /*!
460  * This method is a method that compares \a this and \a other.
461  * This method compares \b all attributes, even names and component names.
462  */
463 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
464 {
465   if(!other)
466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
467   std::ostringstream oss; oss.precision(15);
468   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
469   if(!otherC)
470     {
471       reason="mesh given in input is not castable in MEDCouplingUMesh !";
472       return false;
473     }
474   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
475     return false;
476   if(_mesh_dim!=otherC->_mesh_dim)
477     {
478       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
479       reason=oss.str();
480       return false;
481     }
482   if(_types!=otherC->_types)
483     {
484       oss << "umesh geometric type mismatch :\nThis geometric types are :";
485       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
486         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
487       oss << "\nOther geometric types are :";
488       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
489         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
490       reason=oss.str();
491       return false;
492     }
493   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
494     if(_nodal_connec==0 || otherC->_nodal_connec==0)
495       {
496         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
497         return false;
498       }
499   if(_nodal_connec!=otherC->_nodal_connec)
500     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
501       {
502         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
503         return false;
504       }
505   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
506     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
507       {
508         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
509         return false;
510       }
511   if(_nodal_connec_index!=otherC->_nodal_connec_index)
512     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
513       {
514         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
515         return false;
516       }
517   return true;
518 }
519
520 /*!
521  * Checks if data arrays of this mesh (node coordinates, nodal
522  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
523  * not considered.
524  *  \param [in] other - the mesh to compare with.
525  *  \param [in] prec - precision value used to compare node coordinates.
526  *  \return bool - \a true if the two meshes are same.
527  */
528 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
529 {
530   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
531   if(!otherC)
532     return false;
533   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
534     return false;
535   if(_mesh_dim!=otherC->_mesh_dim)
536     return false;
537   if(_types!=otherC->_types)
538     return false;
539   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
540     if(_nodal_connec==0 || otherC->_nodal_connec==0)
541       return false;
542   if(_nodal_connec!=otherC->_nodal_connec)
543     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
544       return false;
545   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
546     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
547       return false;
548   if(_nodal_connec_index!=otherC->_nodal_connec_index)
549     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
550       return false;
551   return true;
552 }
553
554 /*!
555  * Checks if \a this and \a other meshes are geometrically equivalent with high
556  * probability, else an exception is thrown. The meshes are considered equivalent if
557  * (1) meshes contain the same number of nodes and the same number of elements of the
558  * same types (2) three cells of the two meshes (first, last and middle) are based
559  * on coincident nodes (with a specified precision).
560  *  \param [in] other - the mesh to compare with.
561  *  \param [in] prec - the precision used to compare nodes of the two meshes.
562  *  \throw If the two meshes do not match.
563  */
564 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
565 {
566   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
567   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
568   if(!otherC)
569     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
570 }
571
572 /*!
573  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
574  * cells each node belongs to.
575  * \warning For speed reasons, this method does not check if node ids in the nodal
576  *          connectivity correspond to the size of node coordinates array.
577  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
578  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
579  *        dividing cell ids in \a revNodal into groups each referring to one
580  *        node. Its every element (except the last one) is an index pointing to the
581  *         first id of a group of cells. For example cells sharing the node #1 are 
582  *        described by following range of indices: 
583  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
584  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
585  *        Number of cells sharing the *i*-th node is
586  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
587  * \throw If the coordinates array is not set.
588  * \throw If the nodal connectivity of cells is not defined.
589  * 
590  * \if ENABLE_EXAMPLES
591  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
592  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
593  * \endif
594  */
595 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
596 {
597   checkFullyDefined();
598   int nbOfNodes=getNumberOfNodes();
599   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
600   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
601   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
602   const int *conn=_nodal_connec->getConstPointer();
603   const int *connIndex=_nodal_connec_index->getConstPointer();
604   int nbOfCells=getNumberOfCells();
605   int nbOfEltsInRevNodal=0;
606   for(int eltId=0;eltId<nbOfCells;eltId++)
607     {
608       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
609       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
610       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
611         if(*iter>=0)//for polyhedrons
612           {
613             nbOfEltsInRevNodal++;
614             revNodalIndxPtr[(*iter)+1]++;
615           }
616     }
617   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
618   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
619   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
620   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
621   for(int eltId=0;eltId<nbOfCells;eltId++)
622     {
623       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
624       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
625       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
626         if(*iter>=0)//for polyhedrons
627           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
628     }
629 }
630
631 /// @cond INTERNAL
632
633 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
634 {
635   return id;
636 }
637
638 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
639 {
640   if(!compute)
641     return id+1;
642   else
643     {
644       if(cm.getOrientationStatus(nb,conn1,conn2))
645         return id+1;
646       else
647         return -(id+1);
648     }
649 }
650
651 class MinusOneSonsGenerator
652 {
653 public:
654   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
655   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
656   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
657   static const int DELTA=1;
658 private:
659   const INTERP_KERNEL::CellModel& _cm;
660 };
661
662 class MinusOneSonsGeneratorBiQuadratic
663 {
664 public:
665   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
666   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
667   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
668   static const int DELTA=1;
669 private:
670   const INTERP_KERNEL::CellModel& _cm;
671 };
672
673 class MinusTwoSonsGenerator
674 {
675 public:
676   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
677   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
678   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
679   static const int DELTA=2;
680 private:
681   const INTERP_KERNEL::CellModel& _cm;
682 };
683
684 /// @endcond
685
686 /*!
687  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
688  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
689  * describing correspondence between cells of \a this and the result meshes are
690  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
691  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
692  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
693  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
694  * \warning For speed reasons, this method does not check if node ids in the nodal
695  *          connectivity correspond to the size of node coordinates array.
696  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
697  *          to write this mesh to the MED file, its cells must be sorted using
698  *          sortCellsInMEDFileFrmt().
699  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
700  *         each cell of \a this mesh.
701  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
702  *        dividing cell ids in \a desc into groups each referring to one
703  *        cell of \a this mesh. Its every element (except the last one) is an index
704  *        pointing to the first id of a group of cells. For example cells of the
705  *        result mesh bounding the cell #1 of \a this mesh are described by following
706  *        range of indices:
707  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
708  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
709  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
710  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
711  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
712  *         by each cell of the result mesh.
713  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
714  *        in the result mesh,
715  *        dividing cell ids in \a revDesc into groups each referring to one
716  *        cell of the result mesh the same way as \a descIndx divides \a desc.
717  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
718  *        delete this mesh using decrRef() as it is no more needed.
719  *  \throw If the coordinates array is not set.
720  *  \throw If the nodal connectivity of cells is node defined.
721  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
722  *         revDescIndx == NULL.
723  * 
724  *  \if ENABLE_EXAMPLES
725  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
726  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
727  *  \endif
728  * \sa buildDescendingConnectivity2()
729  */
730 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
731 {
732   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
733 }
734
735 /*!
736  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
737  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
738  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
739  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
740  * \sa MEDCouplingUMesh::buildDescendingConnectivity
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
743 {
744   checkFullyDefined();
745   if(getMeshDimension()!=3)
746     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
747   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
748 }
749
750 /*!
751  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
752  * this->getMeshDimension(), that bound cells of \a this mesh. In
753  * addition arrays describing correspondence between cells of \a this and the result
754  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
755  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
756  *  mesh. This method differs from buildDescendingConnectivity() in that apart
757  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
758  * result meshes. So a positive id means that order of nodes in corresponding cells
759  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
760  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
761  * i.e. cell ids are one-based.
762  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
763  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
764  * \warning For speed reasons, this method does not check if node ids in the nodal
765  *          connectivity correspond to the size of node coordinates array.
766  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
767  *          to write this mesh to the MED file, its cells must be sorted using
768  *          sortCellsInMEDFileFrmt().
769  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
770  *         each cell of \a this mesh.
771  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
772  *        dividing cell ids in \a desc into groups each referring to one
773  *        cell of \a this mesh. Its every element (except the last one) is an index
774  *        pointing to the first id of a group of cells. For example cells of the
775  *        result mesh bounding the cell #1 of \a this mesh are described by following
776  *        range of indices:
777  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
778  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
779  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
780  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
781  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
782  *         by each cell of the result mesh.
783  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
784  *        in the result mesh,
785  *        dividing cell ids in \a revDesc into groups each referring to one
786  *        cell of the result mesh the same way as \a descIndx divides \a desc.
787  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
788  *        shares the node coordinates array with \a this mesh. The caller is to
789  *        delete this mesh using decrRef() as it is no more needed.
790  *  \throw If the coordinates array is not set.
791  *  \throw If the nodal connectivity of cells is node defined.
792  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
793  *         revDescIndx == NULL.
794  * 
795  *  \if ENABLE_EXAMPLES
796  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
797  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
798  *  \endif
799  * \sa buildDescendingConnectivity()
800  */
801 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
802 {
803   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
804 }
805
806 /*!
807  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
808  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
809  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
810  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
811  *
812  * \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
813  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
814  * \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.
815  */
816 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
817 {
818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
822   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
823   meshDM1=0;
824   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
825 }
826
827 /*!
828  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
829  * 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,
830  * excluding a set of meshdim-1 cells in input descending connectivity.
831  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
832  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
833  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
834  *
835  * \param [in] desc descending connectivity array.
836  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
837  * \param [in] revDesc reverse descending connectivity array.
838  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
839  * \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
840  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
841  * \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.
842  */
843 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
844                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
845 {
846   if(!desc || !descIndx || !revDesc || !revDescIndx)
847     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
848   const int *descPtr=desc->getConstPointer();
849   const int *descIPtr=descIndx->getConstPointer();
850   const int *revDescPtr=revDesc->getConstPointer();
851   const int *revDescIPtr=revDescIndx->getConstPointer();
852   //
853   int nbCells=descIndx->getNumberOfTuples()-1;
854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
856   int *out1Ptr=out1->getPointer();
857   *out1Ptr++=0;
858   out0->reserve(desc->getNumberOfTuples());
859   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
860     {
861       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
862         {
863           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
864           s.erase(i);
865           out0->insertAtTheEnd(s.begin(),s.end());
866         }
867       *out1Ptr=out0->getNumberOfTuples();
868     }
869   neighbors=out0.retn();
870   neighborsIndx=out1.retn();
871 }
872
873 /*!
874  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
875  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
876  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
877  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
878  *
879  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
880  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
881  * \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.
882  */
883 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
884 {
885   checkFullyDefined();
886   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
888   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
889   switch(mdim)
890   {
891     case 3:
892       {
893         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
894         break;
895       }
896     case 2:
897       {
898         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
899         break;
900       }
901     case 1:
902       {
903         mesh1D=const_cast<MEDCouplingUMesh *>(this);
904         mesh1D->incrRef();
905         break;
906       }
907     default:
908       {
909         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
910       }
911   }
912   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
913   mesh1D->getReverseNodalConnectivity(desc,descIndx);
914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
915   ret0->alloc(desc->getNumberOfTuples(),1);
916   int *r0Pt(ret0->getPointer());
917   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
918   for(int i=0;i<nbNodes;i++,rni++)
919     {
920       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
921         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
922     }
923   neighbors=ret0.retn();
924   neighborsIdx=descIndx.retn();
925 }
926
927 /// @cond INTERNAL
928
929 /*!
930  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
931  * For speed reasons no check of this will be done.
932  */
933 template<class SonsGenerator>
934 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
935 {
936   if(!desc || !descIndx || !revDesc || !revDescIndx)
937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
938   checkConnectivityFullyDefined();
939   int nbOfCells=getNumberOfCells();
940   int nbOfNodes=getNumberOfNodes();
941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
942   int *revNodalIndxPtr=revNodalIndx->getPointer();
943   const int *conn=_nodal_connec->getConstPointer();
944   const int *connIndex=_nodal_connec_index->getConstPointer();
945   std::string name="Mesh constituent of "; name+=getName();
946   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
947   ret->setCoords(getCoords());
948   ret->allocateCells(2*nbOfCells);
949   descIndx->alloc(nbOfCells+1,1);
950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
951   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
952   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
953     {
954       int pos=connIndex[eltId];
955       int posP1=connIndex[eltId+1];
956       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
957       SonsGenerator sg(cm);
958       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
959       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
960       for(unsigned i=0;i<nbOfSons;i++)
961         {
962           INTERP_KERNEL::NormalizedCellType cmsId;
963           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
964           for(unsigned k=0;k<nbOfNodesSon;k++)
965             if(tmp[k]>=0)
966               revNodalIndxPtr[tmp[k]+1]++;
967           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
968           revDesc2->pushBackSilent(eltId);
969         }
970       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
971     }
972   int nbOfCellsM1=ret->getNumberOfCells();
973   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
975   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
976   int *revNodalPtr=revNodal->getPointer();
977   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
978   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
979   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
980     {
981       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
982       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
983       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
984         if(*iter>=0)//for polyhedrons
985           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
986     }
987   //
988   DataArrayInt *commonCells=0,*commonCellsI=0;
989   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
991   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
992   int newNbOfCellsM1=-1;
993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
994                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
995   std::vector<bool> isImpacted(nbOfCellsM1,false);
996   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
997     for(int work2=work[0];work2!=work[1];work2++)
998       isImpacted[commonCellsPtr[work2]]=true;
999   const int *o2nM1Ptr=o2nM1->getConstPointer();
1000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1001   const int *n2oM1Ptr=n2oM1->getConstPointer();
1002   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1003   ret2->copyTinyInfoFrom(this);
1004   desc->alloc(descIndx->back(),1);
1005   int *descPtr=desc->getPointer();
1006   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1007   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1008     {
1009       if(!isImpacted[i])
1010         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1011       else
1012         {
1013           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1014             {
1015               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1016               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1017             }
1018           else
1019             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1020         }
1021     }
1022   revDesc->reserve(newNbOfCellsM1);
1023   revDescIndx->alloc(newNbOfCellsM1+1,1);
1024   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1025   const int *revDesc2Ptr=revDesc2->getConstPointer();
1026   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1027     {
1028       int oldCellIdM1=n2oM1Ptr[i];
1029       if(!isImpacted[oldCellIdM1])
1030         {
1031           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1032           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1033         }
1034       else
1035         {
1036           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1037             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1038           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1039           commonCellsIPtr++;
1040         }
1041     }
1042   //
1043   return ret2.retn();
1044 }
1045
1046 struct MEDCouplingAccVisit
1047 {
1048   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1049   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1050   int _new_nb_of_nodes;
1051 };
1052
1053 /// @endcond
1054
1055 /*!
1056  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1057  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1058  * array of cell ids. Pay attention that after conversion all algorithms work slower
1059  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1060  * conversion due presence of invalid ids in the array of cells to convert, as a
1061  * result \a this mesh contains some already converted elements. In this case the 2D
1062  * mesh remains valid but 3D mesh becomes \b inconsistent!
1063  *  \warning This method can significantly modify the order of geometric types in \a this,
1064  *          hence, to write this mesh to the MED file, its cells must be sorted using
1065  *          sortCellsInMEDFileFrmt().
1066  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1067  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1068  *         cellIdsToConvertBg.
1069  *  \throw If the coordinates array is not set.
1070  *  \throw If the nodal connectivity of cells is node defined.
1071  *  \throw If dimension of \a this mesh is not either 2 or 3.
1072  *
1073  *  \if ENABLE_EXAMPLES
1074  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1075  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1076  *  \endif
1077  */
1078 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1079 {
1080   checkFullyDefined();
1081   int dim=getMeshDimension();
1082   if(dim<2 || dim>3)
1083     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1084   int nbOfCells(getNumberOfCells());
1085   if(dim==2)
1086     {
1087       const int *connIndex=_nodal_connec_index->getConstPointer();
1088       int *conn=_nodal_connec->getPointer();
1089       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1090         {
1091           if(*iter>=0 && *iter<nbOfCells)
1092             {
1093               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1094               if(!cm.isQuadratic())
1095                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1096               else
1097                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1098             }
1099           else
1100             {
1101               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1102               oss << " in range [0," << nbOfCells << ") !";
1103               throw INTERP_KERNEL::Exception(oss.str().c_str());
1104             }
1105         }
1106     }
1107   else
1108     {
1109       int *connIndex(_nodal_connec_index->getPointer());
1110       const int *connOld(_nodal_connec->getConstPointer());
1111       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1112       std::vector<bool> toBeDone(nbOfCells,false);
1113       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1114         {
1115           if(*iter>=0 && *iter<nbOfCells)
1116             toBeDone[*iter]=true;
1117           else
1118             {
1119               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1120               oss << " in range [0," << nbOfCells << ") !";
1121               throw INTERP_KERNEL::Exception(oss.str().c_str());
1122             }
1123         }
1124       for(int cellId=0;cellId<nbOfCells;cellId++)
1125         {
1126           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1127           int lgthOld(posP1-pos-1);
1128           if(toBeDone[cellId])
1129             {
1130               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1131               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1132               int *tmp(new int[nbOfFaces*lgthOld+1]);
1133               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1134               for(unsigned j=0;j<nbOfFaces;j++)
1135                 {
1136                   INTERP_KERNEL::NormalizedCellType type;
1137                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1138                   work+=offset;
1139                   *work++=-1;
1140                 }
1141               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1142               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1143               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1144               delete [] tmp;
1145             }
1146           else
1147             {
1148               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1149               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1150             }
1151         }
1152       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1153     }
1154   computeTypes();
1155 }
1156
1157 /*!
1158  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1159  * polyhedrons (if \a this is a 3D mesh).
1160  *  \warning As this method is purely for user-friendliness and no optimization is
1161  *          done to avoid construction of a useless vector, this method can be costly
1162  *          in memory.
1163  *  \throw If the coordinates array is not set.
1164  *  \throw If the nodal connectivity of cells is node defined.
1165  *  \throw If dimension of \a this mesh is not either 2 or 3.
1166  */
1167 void MEDCouplingUMesh::convertAllToPoly()
1168 {
1169   int nbOfCells=getNumberOfCells();
1170   std::vector<int> cellIds(nbOfCells);
1171   for(int i=0;i<nbOfCells;i++)
1172     cellIds[i]=i;
1173   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1174 }
1175
1176 /*!
1177  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1178  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1179  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1180  * base facet of the volume and the second half of nodes describes an opposite facet
1181  * having the same number of nodes as the base one. This method converts such
1182  * connectivity to a valid polyhedral format where connectivity of each facet is
1183  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1184  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1185  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1186  * a correct orientation of the first facet of a polyhedron, else orientation of a
1187  * corrected cell is reverse.<br>
1188  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1189  * it releases the user from boring description of polyhedra connectivity in the valid
1190  * format.
1191  *  \throw If \a this->getMeshDimension() != 3.
1192  *  \throw If \a this->getSpaceDimension() != 3.
1193  *  \throw If the nodal connectivity of cells is not defined.
1194  *  \throw If the coordinates array is not set.
1195  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1196  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1197  *
1198  *  \if ENABLE_EXAMPLES
1199  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1200  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1201  *  \endif
1202  */
1203 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1204 {
1205   checkFullyDefined();
1206   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1208   int nbOfCells=getNumberOfCells();
1209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1210   newCi->alloc(nbOfCells+1,1);
1211   int *newci=newCi->getPointer();
1212   const int *ci=_nodal_connec_index->getConstPointer();
1213   const int *c=_nodal_connec->getConstPointer();
1214   newci[0]=0;
1215   for(int i=0;i<nbOfCells;i++)
1216     {
1217       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1218       if(type==INTERP_KERNEL::NORM_POLYHED)
1219         {
1220           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1221             {
1222               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1223               throw INTERP_KERNEL::Exception(oss.str().c_str());
1224             }
1225           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1226           if(n2%2!=0)
1227             {
1228               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 !";
1229               throw INTERP_KERNEL::Exception(oss.str().c_str());
1230             }
1231           int n1=(int)(n2/2);
1232           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)
1233         }
1234       else
1235         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1236     }
1237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1238   newC->alloc(newci[nbOfCells],1);
1239   int *newc=newC->getPointer();
1240   for(int i=0;i<nbOfCells;i++)
1241     {
1242       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1243       if(type==INTERP_KERNEL::NORM_POLYHED)
1244         {
1245           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1246           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1247           *newc++=-1;
1248           for(std::size_t j=0;j<n1;j++)
1249             {
1250               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1251               newc[n1+5*j]=-1;
1252               newc[n1+5*j+1]=c[ci[i]+1+j];
1253               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1254               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1255               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1256             }
1257           newc+=n1*6;
1258         }
1259       else
1260         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1261     }
1262   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1263   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1264 }
1265
1266
1267 /*!
1268  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1269  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1270  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1271  *          to write this mesh to the MED file, its cells must be sorted using
1272  *          sortCellsInMEDFileFrmt().
1273  * \return \c true if at least one cell has been converted, \c false else. In the
1274  *         last case the nodal connectivity remains unchanged.
1275  * \throw If the coordinates array is not set.
1276  * \throw If the nodal connectivity of cells is not defined.
1277  * \throw If \a this->getMeshDimension() < 0.
1278  */
1279 bool MEDCouplingUMesh::unPolyze()
1280 {
1281   checkFullyDefined();
1282   int mdim=getMeshDimension();
1283   if(mdim<0)
1284     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1285   if(mdim<=1)
1286     return false;
1287   int nbOfCells=getNumberOfCells();
1288   if(nbOfCells<1)
1289     return false;
1290   int initMeshLgth=getMeshLength();
1291   int *conn=_nodal_connec->getPointer();
1292   int *index=_nodal_connec_index->getPointer();
1293   int posOfCurCell=0;
1294   int newPos=0;
1295   int lgthOfCurCell;
1296   bool ret=false;
1297   for(int i=0;i<nbOfCells;i++)
1298     {
1299       lgthOfCurCell=index[i+1]-posOfCurCell;
1300       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1301       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1302       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1303       int newLgth;
1304       if(cm.isDynamic())
1305         {
1306           switch(cm.getDimension())
1307           {
1308             case 2:
1309               {
1310                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1311                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1312                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1313                 break;
1314               }
1315             case 3:
1316               {
1317                 int nbOfFaces,lgthOfPolyhConn;
1318                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1319                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1320                 break;
1321               }
1322             case 1:
1323               {
1324                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1325                 break;
1326               }
1327           }
1328           ret=ret || (newType!=type);
1329           conn[newPos]=newType;
1330           newPos+=newLgth+1;
1331           posOfCurCell=index[i+1];
1332           index[i+1]=newPos;
1333         }
1334       else
1335         {
1336           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1337           newPos+=lgthOfCurCell;
1338           posOfCurCell+=lgthOfCurCell;
1339           index[i+1]=newPos;
1340         }
1341     }
1342   if(newPos!=initMeshLgth)
1343     _nodal_connec->reAlloc(newPos);
1344   if(ret)
1345     computeTypes();
1346   return ret;
1347 }
1348
1349 /*!
1350  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1351  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1352  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1353  *
1354  * \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 
1355  *             precision.
1356  */
1357 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1358 {
1359   checkFullyDefined();
1360   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1361     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1363   coords->recenterForMaxPrecision(eps);
1364   //
1365   int nbOfCells=getNumberOfCells();
1366   const int *conn=_nodal_connec->getConstPointer();
1367   const int *index=_nodal_connec_index->getConstPointer();
1368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1369   connINew->alloc(nbOfCells+1,1);
1370   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1372   bool changed=false;
1373   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1374     {
1375       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1376         {
1377           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1378           changed=true;
1379         }
1380       else
1381         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1382       *connINewPtr=connNew->getNumberOfTuples();
1383     }
1384   if(changed)
1385     setConnectivity(connNew,connINew,false);
1386 }
1387
1388 /*!
1389  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1390  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1391  * the format of returned DataArrayInt instance.
1392  * 
1393  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1394  * \sa MEDCouplingUMesh::getNodeIdsInUse
1395  */
1396 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1397 {
1398   checkConnectivityFullyDefined();
1399   int nbOfCells=getNumberOfCells();
1400   const int *connIndex=_nodal_connec_index->getConstPointer();
1401   const int *conn=_nodal_connec->getConstPointer();
1402   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1403   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1404   std::vector<bool> retS(maxElt,false);
1405   for(int i=0;i<nbOfCells;i++)
1406     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1407       if(conn[j]>=0)
1408         retS[conn[j]]=true;
1409   int sz=0;
1410   for(int i=0;i<maxElt;i++)
1411     if(retS[i])
1412       sz++;
1413   DataArrayInt *ret=DataArrayInt::New();
1414   ret->alloc(sz,1);
1415   int *retPtr=ret->getPointer();
1416   for(int i=0;i<maxElt;i++)
1417     if(retS[i])
1418       *retPtr++=i;
1419   return ret;
1420 }
1421
1422 /*!
1423  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1424  * \sa MEDCouplingUMesh::getNodeIdsInUse
1425  */
1426 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1427 {
1428   int nbOfNodes=(int)nodeIdsInUse.size();
1429   int nbOfCells=getNumberOfCells();
1430   const int *connIndex=_nodal_connec_index->getConstPointer();
1431   const int *conn=_nodal_connec->getConstPointer();
1432   for(int i=0;i<nbOfCells;i++)
1433     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1434       if(conn[j]>=0)
1435         {
1436           if(conn[j]<nbOfNodes)
1437             nodeIdsInUse[conn[j]]=true;
1438           else
1439             {
1440               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1441               throw INTERP_KERNEL::Exception(oss.str().c_str());
1442             }
1443         }
1444 }
1445
1446 /*!
1447  * Finds nodes not used in any cell and returns an array giving a new id to every node
1448  * by excluding the unused nodes, for which the array holds -1. The result array is
1449  * a mapping in "Old to New" mode. 
1450  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1451  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1452  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1453  *          if the node is unused or a new id else. The caller is to delete this
1454  *          array using decrRef() as it is no more needed.  
1455  *  \throw If the coordinates array is not set.
1456  *  \throw If the nodal connectivity of cells is not defined.
1457  *  \throw If the nodal connectivity includes an invalid id.
1458  *
1459  *  \if ENABLE_EXAMPLES
1460  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1461  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1462  *  \endif
1463  * \sa computeNodeIdsAlg()
1464  */
1465 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1466 {
1467   nbrOfNodesInUse=-1;
1468   int nbOfNodes=getNumberOfNodes();
1469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1470   ret->alloc(nbOfNodes,1);
1471   int *traducer=ret->getPointer();
1472   std::fill(traducer,traducer+nbOfNodes,-1);
1473   int nbOfCells=getNumberOfCells();
1474   const int *connIndex=_nodal_connec_index->getConstPointer();
1475   const int *conn=_nodal_connec->getConstPointer();
1476   for(int i=0;i<nbOfCells;i++)
1477     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1478       if(conn[j]>=0)
1479         {
1480           if(conn[j]<nbOfNodes)
1481             traducer[conn[j]]=1;
1482           else
1483             {
1484               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1485               throw INTERP_KERNEL::Exception(oss.str().c_str());
1486             }
1487         }
1488   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1489   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1490   return ret.retn();
1491 }
1492
1493 /*!
1494  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1495  * For each cell in \b this the number of nodes constituting cell is computed.
1496  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1497  * So for pohyhedrons some nodes can be counted several times in the returned result.
1498  * 
1499  * \return a newly allocated array
1500  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1501  */
1502 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1503 {
1504   checkConnectivityFullyDefined();
1505   int nbOfCells=getNumberOfCells();
1506   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1507   ret->alloc(nbOfCells,1);
1508   int *retPtr=ret->getPointer();
1509   const int *conn=getNodalConnectivity()->getConstPointer();
1510   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1511   for(int i=0;i<nbOfCells;i++,retPtr++)
1512     {
1513       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1514         *retPtr=connI[i+1]-connI[i]-1;
1515       else
1516         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1517     }
1518   return ret.retn();
1519 }
1520
1521 /*!
1522  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1523  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1524  *
1525  * \return DataArrayInt * - new object to be deallocated by the caller.
1526  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1527  */
1528 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1529 {
1530   checkConnectivityFullyDefined();
1531   int nbOfCells=getNumberOfCells();
1532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1533   ret->alloc(nbOfCells,1);
1534   int *retPtr=ret->getPointer();
1535   const int *conn=getNodalConnectivity()->getConstPointer();
1536   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1537   for(int i=0;i<nbOfCells;i++,retPtr++)
1538     {
1539       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1540       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1541         *retPtr=(int)s.size();
1542       else
1543         {
1544           s.erase(-1);
1545           *retPtr=(int)s.size();
1546         }
1547     }
1548   return ret.retn();
1549 }
1550
1551 /*!
1552  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1553  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1554  * 
1555  * \return a newly allocated array
1556  */
1557 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1558 {
1559   checkConnectivityFullyDefined();
1560   int nbOfCells=getNumberOfCells();
1561   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1562   ret->alloc(nbOfCells,1);
1563   int *retPtr=ret->getPointer();
1564   const int *conn=getNodalConnectivity()->getConstPointer();
1565   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1566   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1567     {
1568       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1569       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1570     }
1571   return ret.retn();
1572 }
1573
1574 /*!
1575  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1576  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1577  * array mean that the corresponding old node is no more used. 
1578  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1579  *           this->getNumberOfNodes() before call of this method. The caller is to
1580  *           delete this array using decrRef() as it is no more needed. 
1581  *  \throw If the coordinates array is not set.
1582  *  \throw If the nodal connectivity of cells is not defined.
1583  *  \throw If the nodal connectivity includes an invalid id.
1584  *
1585  *  \if ENABLE_EXAMPLES
1586  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1587  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1588  *  \endif
1589  */
1590 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1591 {
1592   return MEDCouplingPointSet::zipCoordsTraducer();
1593 }
1594
1595 /*!
1596  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1597  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1598  */
1599 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1600 {
1601   switch(compType)
1602   {
1603     case 0:
1604       return AreCellsEqual0(conn,connI,cell1,cell2);
1605     case 1:
1606       return AreCellsEqual1(conn,connI,cell1,cell2);
1607     case 2:
1608       return AreCellsEqual2(conn,connI,cell1,cell2);
1609     case 3:
1610       return AreCellsEqual3(conn,connI,cell1,cell2);
1611     case 7:
1612       return AreCellsEqual7(conn,connI,cell1,cell2);
1613   }
1614   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1615 }
1616
1617 /*!
1618  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1619  */
1620 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1621 {
1622   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1623     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1624   return 0;
1625 }
1626
1627 /*!
1628  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1629  */
1630 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1631 {
1632   int sz=connI[cell1+1]-connI[cell1];
1633   if(sz==connI[cell2+1]-connI[cell2])
1634     {
1635       if(conn[connI[cell1]]==conn[connI[cell2]])
1636         {
1637           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1638           unsigned dim=cm.getDimension();
1639           if(dim!=3)
1640             {
1641               if(dim!=1)
1642                 {
1643                   int sz1=2*(sz-1);
1644                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1645                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1646                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1647                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1648                   return work!=tmp+sz1?1:0;
1649                 }
1650               else
1651                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1652             }
1653           else
1654             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1655         }
1656     }
1657   return 0;
1658 }
1659
1660 /*!
1661  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1662  */
1663 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1664 {
1665   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1666     {
1667       if(conn[connI[cell1]]==conn[connI[cell2]])
1668         {
1669           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1670           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1671           return s1==s2?1:0;
1672         }
1673     }
1674   return 0;
1675 }
1676
1677 /*!
1678  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1679  */
1680 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1681 {
1682   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1683     {
1684       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1685       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1686       return s1==s2?1:0;
1687     }
1688   return 0;
1689 }
1690
1691 /*!
1692  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1693  */
1694 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1695 {
1696   int sz=connI[cell1+1]-connI[cell1];
1697   if(sz==connI[cell2+1]-connI[cell2])
1698     {
1699       if(conn[connI[cell1]]==conn[connI[cell2]])
1700         {
1701           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1702           unsigned dim=cm.getDimension();
1703           if(dim!=3)
1704             {
1705               if(dim!=1)
1706                 {
1707                   int sz1=2*(sz-1);
1708                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1709                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1710                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1711                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1712                   if(work!=tmp+sz1)
1713                     return 1;
1714                   else
1715                     {
1716                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1717                       std::reverse_iterator<int *> it2((int *)tmp);
1718                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1719                         return 2;
1720                       else
1721                         return 0;
1722                     }
1723
1724                   return work!=tmp+sz1?1:0;
1725                 }
1726               else
1727                 {//case of SEG2 and SEG3
1728                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1729                     return 1;
1730                   if(!cm.isQuadratic())
1731                     {
1732                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1733                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1734                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1735                         return 2;
1736                       return 0;
1737                     }
1738                   else
1739                     {
1740                       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])
1741                         return 2;
1742                       return 0;
1743                     }
1744                 }
1745             }
1746           else
1747             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1748         }
1749     }
1750   return 0;
1751 }
1752
1753 /*!
1754  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1755  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1756  * and result remains unchanged.
1757  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1758  * If in 'candidates' pool -1 value is considered as an empty value.
1759  * WARNING this method returns only ONE set of result !
1760  */
1761 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1762 {
1763   if(candidates.size()<1)
1764     return false;
1765   bool ret=false;
1766   std::vector<int>::const_iterator iter=candidates.begin();
1767   int start=(*iter++);
1768   for(;iter!=candidates.end();iter++)
1769     {
1770       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1771       if(status!=0)
1772         {
1773           if(!ret)
1774             {
1775               result->pushBackSilent(start);
1776               ret=true;
1777             }
1778           if(status==1)
1779             result->pushBackSilent(*iter);
1780           else
1781             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1782         }
1783     }
1784   return ret;
1785 }
1786
1787 /*!
1788  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1789  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1790  *
1791  * \param [in] compType input specifying the technique used to compare cells each other.
1792  *   - 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.
1793  *   - 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)
1794  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1795  *   - 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
1796  * can be used for users not sensitive to orientation of cell
1797  * \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.
1798  * \param [out] commonCells
1799  * \param [out] commonCellsI
1800  * \return the correspondance array old to new in a newly allocated array.
1801  * 
1802  */
1803 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1804 {
1805   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1806   getReverseNodalConnectivity(revNodal,revNodalI);
1807   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1808 }
1809
1810 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1811                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1812 {
1813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1814   int nbOfCells=nodalI->getNumberOfTuples()-1;
1815   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1816   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1817   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1818   std::vector<bool> isFetched(nbOfCells,false);
1819   if(startCellId==0)
1820     {
1821       for(int i=0;i<nbOfCells;i++)
1822         {
1823           if(!isFetched[i])
1824             {
1825               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1826               std::vector<int> v,v2;
1827               if(connOfNode!=connPtr+connIPtr[i+1])
1828                 {
1829                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1830                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1831                   connOfNode++;
1832                 }
1833               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1834                 if(*connOfNode>=0)
1835                   {
1836                     v=v2;
1837                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1838                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1839                     v2.resize(std::distance(v2.begin(),it));
1840                   }
1841               if(v2.size()>1)
1842                 {
1843                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1844                     {
1845                       int pos=commonCellsI->back();
1846                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1847                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1848                         isFetched[*it]=true;
1849                     }
1850                 }
1851             }
1852         }
1853     }
1854   else
1855     {
1856       for(int i=startCellId;i<nbOfCells;i++)
1857         {
1858           if(!isFetched[i])
1859             {
1860               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1861               std::vector<int> v,v2;
1862               if(connOfNode!=connPtr+connIPtr[i+1])
1863                 {
1864                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1865                   connOfNode++;
1866                 }
1867               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1868                 if(*connOfNode>=0)
1869                   {
1870                     v=v2;
1871                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1872                     v2.resize(std::distance(v2.begin(),it));
1873                   }
1874               if(v2.size()>1)
1875                 {
1876                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1877                     {
1878                       int pos=commonCellsI->back();
1879                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1880                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1881                         isFetched[*it]=true;
1882                     }
1883                 }
1884             }
1885         }
1886     }
1887   commonCellsArr=commonCells.retn();
1888   commonCellsIArr=commonCellsI.retn();
1889 }
1890
1891 /*!
1892  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1893  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1894  * than \a other->getNumberOfCells() in the returned array means that there is no
1895  * corresponding cell in \a this mesh.
1896  * It is expected that \a this and \a other meshes share the same node coordinates
1897  * array, if it is not so an exception is thrown. 
1898  *  \param [in] other - the mesh to compare with.
1899  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1900  *         valid values [0,1,2], see zipConnectivityTraducer().
1901  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1902  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1903  *         values. The caller is to delete this array using
1904  *         decrRef() as it is no more needed.
1905  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1906  *         mesh.
1907  *
1908  *  \if ENABLE_EXAMPLES
1909  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1910  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1911  *  \endif
1912  *  \sa checkDeepEquivalOnSameNodesWith()
1913  *  \sa checkGeoEquivalWith()
1914  */
1915 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1916 {
1917   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1918   int nbOfCells=getNumberOfCells();
1919   static const int possibleCompType[]={0,1,2};
1920   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1921     {
1922       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1923       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1924       oss << " !";
1925       throw INTERP_KERNEL::Exception(oss.str().c_str());
1926     }
1927   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1928   arr=o2n->substr(nbOfCells);
1929   arr->setName(other->getName());
1930   int tmp;
1931   if(other->getNumberOfCells()==0)
1932     return true;
1933   return arr->getMaxValue(tmp)<nbOfCells;
1934 }
1935
1936 /*!
1937  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1938  * This method tries to determine if \b other is fully included in \b this.
1939  * The main difference is that this method is not expected to throw exception.
1940  * This method has two outputs :
1941  *
1942  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1943  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1944  */
1945 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1946 {
1947   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1948   DataArrayInt *commonCells=0,*commonCellsI=0;
1949   int thisNbCells=getNumberOfCells();
1950   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1952   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1953   int otherNbCells=other->getNumberOfCells();
1954   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1955   arr2->alloc(otherNbCells,1);
1956   arr2->fillWithZero();
1957   int *arr2Ptr=arr2->getPointer();
1958   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1959   for(int i=0;i<nbOfCommon;i++)
1960     {
1961       int start=commonCellsPtr[commonCellsIPtr[i]];
1962       if(start<thisNbCells)
1963         {
1964           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1965             {
1966               int sig=commonCellsPtr[j]>0?1:-1;
1967               int val=std::abs(commonCellsPtr[j])-1;
1968               if(val>=thisNbCells)
1969                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1970             }
1971         }
1972     }
1973   arr2->setName(other->getName());
1974   if(arr2->presenceOfValue(0))
1975     return false;
1976   arr=arr2.retn();
1977   return true;
1978 }
1979
1980 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1981 {
1982   if(!other)
1983     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1984   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1985   if(!otherC)
1986     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1987   std::vector<const MEDCouplingUMesh *> ms(2);
1988   ms[0]=this;
1989   ms[1]=otherC;
1990   return MergeUMeshesOnSameCoords(ms);
1991 }
1992
1993 /*!
1994  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1995  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1996  * cellIds is not given explicitely but by a range python like.
1997  * 
1998  * \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.
1999  * \return a newly allocated
2000  * 
2001  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2002  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2003  */
2004 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2005 {
2006   if(getMeshDimension()!=-1)
2007     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2008   else
2009     {
2010       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2011       if(newNbOfCells!=1)
2012         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2013       if(start!=0)
2014         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2015       incrRef();
2016       return const_cast<MEDCouplingUMesh *>(this);
2017     }
2018 }
2019
2020 /*!
2021  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2022  * The result mesh shares or not the node coordinates array with \a this mesh depending
2023  * on \a keepCoords parameter.
2024  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2025  *           to write this mesh to the MED file, its cells must be sorted using
2026  *           sortCellsInMEDFileFrmt().
2027  *  \param [in] begin - an array of cell ids to include to the new mesh.
2028  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2029  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2030  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2031  *         by calling zipCoords().
2032  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2033  *         to delete this mesh using decrRef() as it is no more needed. 
2034  *  \throw If the coordinates array is not set.
2035  *  \throw If the nodal connectivity of cells is not defined.
2036  *  \throw If any cell id in the array \a begin is not valid.
2037  *
2038  *  \if ENABLE_EXAMPLES
2039  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2040  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2041  *  \endif
2042  */
2043 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2044 {
2045   if(getMeshDimension()!=-1)
2046     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2047   else
2048     {
2049       if(end-begin!=1)
2050         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2051       if(begin[0]!=0)
2052         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2053       incrRef();
2054       return const_cast<MEDCouplingUMesh *>(this);
2055     }
2056 }
2057
2058 /*!
2059  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2060  *
2061  * 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.
2062  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2063  * The number of cells of \b this will remain the same with this method.
2064  *
2065  * \param [in] begin begin of cell ids (included) of cells in this to assign
2066  * \param [in] end end of cell ids (excluded) of cells in this to assign
2067  * \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 ).
2068  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2069  */
2070 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2071 {
2072   checkConnectivityFullyDefined();
2073   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2074   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2075     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2076   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2077     {
2078       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2079       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2080       throw INTERP_KERNEL::Exception(oss.str().c_str());
2081     }
2082   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2083   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2084     {
2085       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2086       throw INTERP_KERNEL::Exception(oss.str().c_str());
2087     }
2088   int nbOfCells=getNumberOfCells();
2089   bool easyAssign=true;
2090   const int *connI=_nodal_connec_index->getConstPointer();
2091   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2092   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2093     {
2094       if(*it>=0 && *it<nbOfCells)
2095         {
2096           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2097         }
2098       else
2099         {
2100           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2101           throw INTERP_KERNEL::Exception(oss.str().c_str());
2102         }
2103     }
2104   if(easyAssign)
2105     {
2106       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2107       computeTypes();
2108     }
2109   else
2110     {
2111       DataArrayInt *arrOut=0,*arrIOut=0;
2112       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2113                                                arrOut,arrIOut);
2114       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2115       setConnectivity(arrOut,arrIOut,true);
2116     }
2117 }
2118
2119 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2120 {
2121   checkConnectivityFullyDefined();
2122   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2123   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2124     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2125   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2126     {
2127       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2128       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2129       throw INTERP_KERNEL::Exception(oss.str().c_str());
2130     }
2131   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2132   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2133     {
2134       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2135       throw INTERP_KERNEL::Exception(oss.str().c_str());
2136     }
2137   int nbOfCells=getNumberOfCells();
2138   bool easyAssign=true;
2139   const int *connI=_nodal_connec_index->getConstPointer();
2140   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2141   int it=start;
2142   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2143     {
2144       if(it>=0 && it<nbOfCells)
2145         {
2146           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2147         }
2148       else
2149         {
2150           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2151           throw INTERP_KERNEL::Exception(oss.str().c_str());
2152         }
2153     }
2154   if(easyAssign)
2155     {
2156       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2157       computeTypes();
2158     }
2159   else
2160     {
2161       DataArrayInt *arrOut=0,*arrIOut=0;
2162       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2163                                                 arrOut,arrIOut);
2164       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2165       setConnectivity(arrOut,arrIOut,true);
2166     }
2167 }                      
2168
2169 /*!
2170  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2171  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2172  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2173  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2174  *
2175  * \param [in] begin input start of array of node ids.
2176  * \param [in] end input end of array of node ids.
2177  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2178  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2179  */
2180 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2181 {
2182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2183   checkConnectivityFullyDefined();
2184   int tmp=-1;
2185   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2186   std::vector<bool> fastFinder(sz,false);
2187   for(const int *work=begin;work!=end;work++)
2188     if(*work>=0 && *work<sz)
2189       fastFinder[*work]=true;
2190   int nbOfCells=getNumberOfCells();
2191   const int *conn=getNodalConnectivity()->getConstPointer();
2192   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2193   for(int i=0;i<nbOfCells;i++)
2194     {
2195       int ref=0,nbOfHit=0;
2196       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2197         if(*work2>=0)
2198           {
2199             ref++;
2200             if(fastFinder[*work2])
2201               nbOfHit++;
2202           }
2203       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2204         cellIdsKept->pushBackSilent(i);
2205     }
2206   cellIdsKeptArr=cellIdsKept.retn();
2207 }
2208
2209 /*!
2210  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2211  * this->getMeshDimension(), that bound some cells of \a this mesh.
2212  * The cells of lower dimension to include to the result mesh are selected basing on
2213  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2214  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2215  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2216  * created mesh shares the node coordinates array with \a this mesh. 
2217  *  \param [in] begin - the array of node ids.
2218  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2219  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2220  *         array \a begin are added, else cells whose any node is in the
2221  *         array \a begin are added.
2222  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2223  *         to delete this mesh using decrRef() as it is no more needed. 
2224  *  \throw If the coordinates array is not set.
2225  *  \throw If the nodal connectivity of cells is not defined.
2226  *  \throw If any node id in \a begin is not valid.
2227  *
2228  *  \if ENABLE_EXAMPLES
2229  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2230  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2231  *  \endif
2232  */
2233 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2234 {
2235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2236   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2237   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2238   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2239   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2240 }
2241
2242 /*!
2243  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2244  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2245  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2246  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2247  *         by calling zipCoords().
2248  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2249  *         to delete this mesh using decrRef() as it is no more needed. 
2250  *  \throw If the coordinates array is not set.
2251  *  \throw If the nodal connectivity of cells is not defined.
2252  *
2253  *  \if ENABLE_EXAMPLES
2254  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2255  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2256  *  \endif
2257  */
2258 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2259 {
2260   DataArrayInt *desc=DataArrayInt::New();
2261   DataArrayInt *descIndx=DataArrayInt::New();
2262   DataArrayInt *revDesc=DataArrayInt::New();
2263   DataArrayInt *revDescIndx=DataArrayInt::New();
2264   //
2265   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2266   revDesc->decrRef();
2267   desc->decrRef();
2268   descIndx->decrRef();
2269   int nbOfCells=meshDM1->getNumberOfCells();
2270   const int *revDescIndxC=revDescIndx->getConstPointer();
2271   std::vector<int> boundaryCells;
2272   for(int i=0;i<nbOfCells;i++)
2273     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2274       boundaryCells.push_back(i);
2275   revDescIndx->decrRef();
2276   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2277   return ret;
2278 }
2279
2280 /*!
2281  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2282  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2283  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2284  */
2285 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2286 {
2287   checkFullyDefined();
2288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2292   //
2293   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2294   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2295   //
2296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2298   const int *revDescPtr=revDesc->getConstPointer();
2299   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2300   int nbOfCells=getNumberOfCells();
2301   std::vector<bool> ret1(nbOfCells,false);
2302   int sz=0;
2303   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2304     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2305       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2306   //
2307   DataArrayInt *ret2=DataArrayInt::New();
2308   ret2->alloc(sz,1);
2309   int *ret2Ptr=ret2->getPointer();
2310   sz=0;
2311   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2312     if(*it)
2313       *ret2Ptr++=sz;
2314   ret2->setName("BoundaryCells");
2315   return ret2;
2316 }
2317
2318 /*!
2319  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2320  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2321  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2322  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2323  *
2324  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2325  * This method method returns cells ids set s = s1 + s2 where :
2326  * 
2327  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2328  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2329  *
2330  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2331  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2332  *
2333  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2334  * \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
2335  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2336  */
2337 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2338 {
2339   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2340     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2341   checkConnectivityFullyDefined();
2342   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2343   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2344     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2349   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2350   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2351   DataArrayInt *idsOtherInConsti=0;
2352   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2353   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2354   if(!b)
2355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2356   std::set<int> s1;
2357   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2358     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2361   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2362   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2363   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2364   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2365   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2366   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2367   neighThisPartAuto=0;
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2369   const int li[2]={0,1};
2370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2371   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2373   s_renum1->sort();
2374   //
2375   cellIdsRk0=s0arr.retn();
2376   cellIdsRk1=s_renum1.retn();
2377 }
2378
2379 /*!
2380  * 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
2381  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2382  * 
2383  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2384  */
2385 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2386 {
2387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2391   //
2392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2393   revDesc=0; desc=0; descIndx=0;
2394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2395   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2396   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2397 }
2398
2399 /*!
2400  * Finds nodes lying on the boundary of \a this mesh.
2401  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2402  *          nodes. The caller is to delete this array using decrRef() as it is no
2403  *          more needed.
2404  *  \throw If the coordinates array is not set.
2405  *  \throw If the nodal connectivity of cells is node defined.
2406  *
2407  *  \if ENABLE_EXAMPLES
2408  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2409  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2410  *  \endif
2411  */
2412 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2413 {
2414   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2415   return skin->computeFetchedNodeIds();
2416 }
2417
2418 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2419 {
2420   incrRef();
2421   return const_cast<MEDCouplingUMesh *>(this);
2422 }
2423
2424 /*!
2425  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2426  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2427  * 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.
2428  * 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.
2429  * 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.
2430  *
2431  * \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
2432  *             parameter is altered during the call.
2433  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2434  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2435  * \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.
2436  *
2437  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2438  */
2439 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2440                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2441 {
2442   checkFullyDefined();
2443   otherDimM1OnSameCoords.checkFullyDefined();
2444   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2446   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2447     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2448   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2449   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2451   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2452   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2453   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2455   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2457   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2458   //
2459   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2461   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2462   DataArrayInt *idsTmp=0;
2463   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2465   if(!b)
2466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2467   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2468   DataArrayInt *tmp0=0,*tmp1=0;
2469   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2473   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2474   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2475   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2476   //
2477   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2478   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2479   nodeIdsToDuplicate=s3.retn();
2480 }
2481
2482 /*!
2483  * This method operates a modification of the connectivity and coords in \b this.
2484  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2485  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2486  * 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
2487  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2488  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2489  * 
2490  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2491  * 
2492  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2493  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2494  */
2495 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2496 {
2497   int nbOfNodes=getNumberOfNodes();
2498   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2499   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2500 }
2501
2502 /*!
2503  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2504  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2505  * This method is a generalization of shiftNodeNumbersInConn().
2506  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2507  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2508  *         this->getNumberOfNodes(), in "Old to New" mode. 
2509  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2510  *  \throw If the nodal connectivity of cells is not defined.
2511  *
2512  *  \if ENABLE_EXAMPLES
2513  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2514  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2515  *  \endif
2516  */
2517 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2518 {
2519   checkConnectivityFullyDefined();
2520   int *conn=getNodalConnectivity()->getPointer();
2521   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2522   int nbOfCells=getNumberOfCells();
2523   for(int i=0;i<nbOfCells;i++)
2524     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2525       {
2526         int& node=conn[iconn];
2527         if(node>=0)//avoid polyhedron separator
2528           {
2529             node=newNodeNumbersO2N[node];
2530           }
2531       }
2532   _nodal_connec->declareAsNew();
2533   updateTime();
2534 }
2535
2536 /*!
2537  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2538  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2539  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2540  * 
2541  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2542  */
2543 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2544 {
2545   checkConnectivityFullyDefined();
2546   int *conn=getNodalConnectivity()->getPointer();
2547   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2548   int nbOfCells=getNumberOfCells();
2549   for(int i=0;i<nbOfCells;i++)
2550     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2551       {
2552         int& node=conn[iconn];
2553         if(node>=0)//avoid polyhedron separator
2554           {
2555             node+=delta;
2556           }
2557       }
2558   _nodal_connec->declareAsNew();
2559   updateTime();
2560 }
2561
2562 /*!
2563  * This method operates a modification of the connectivity in \b this.
2564  * 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.
2565  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2566  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2567  * 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
2568  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2569  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2570  * 
2571  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2572  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2573  * 
2574  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2575  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2576  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2577  */
2578 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2579 {
2580   checkConnectivityFullyDefined();
2581   std::map<int,int> m;
2582   int val=offset;
2583   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2584     m[*work]=val;
2585   int *conn=getNodalConnectivity()->getPointer();
2586   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2587   int nbOfCells=getNumberOfCells();
2588   for(int i=0;i<nbOfCells;i++)
2589     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2590       {
2591         int& node=conn[iconn];
2592         if(node>=0)//avoid polyhedron separator
2593           {
2594             std::map<int,int>::iterator it=m.find(node);
2595             if(it!=m.end())
2596               node=(*it).second;
2597           }
2598       }
2599   updateTime();
2600 }
2601
2602 /*!
2603  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2604  *
2605  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2606  * After the call of this method the number of cells remains the same as before.
2607  *
2608  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2609  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2610  * be strictly in [0;this->getNumberOfCells()).
2611  *
2612  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2613  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2614  * should be contained in[0;this->getNumberOfCells()).
2615  * 
2616  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2617  */
2618 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2619 {
2620   checkConnectivityFullyDefined();
2621   int nbCells=getNumberOfCells();
2622   const int *array=old2NewBg;
2623   if(check)
2624     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2625   //
2626   const int *conn=_nodal_connec->getConstPointer();
2627   const int *connI=_nodal_connec_index->getConstPointer();
2628   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2630   const int *n2oPtr=n2o->begin();
2631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2632   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2633   newConn->copyStringInfoFrom(*_nodal_connec);
2634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2635   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2636   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2637   //
2638   int *newC=newConn->getPointer();
2639   int *newCI=newConnI->getPointer();
2640   int loc=0;
2641   newCI[0]=loc;
2642   for(int i=0;i<nbCells;i++)
2643     {
2644       int pos=n2oPtr[i];
2645       int nbOfElts=connI[pos+1]-connI[pos];
2646       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2647       loc+=nbOfElts;
2648       newCI[i+1]=loc;
2649     }
2650   //
2651   setConnectivity(newConn,newConnI);
2652   if(check)
2653     free(const_cast<int *>(array));
2654 }
2655
2656 /*!
2657  * Finds cells whose bounding boxes intersect a given bounding box.
2658  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2659  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2660  *         zMax (if in 3D). 
2661  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2662  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2663  *         extent of the bounding box of cell to produce an addition to this bounding box.
2664  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2665  *         cells. The caller is to delete this array using decrRef() as it is no more
2666  *         needed. 
2667  *  \throw If the coordinates array is not set.
2668  *  \throw If the nodal connectivity of cells is not defined.
2669  *
2670  *  \if ENABLE_EXAMPLES
2671  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2672  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2673  *  \endif
2674  */
2675 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2676 {
2677   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2678   if(getMeshDimension()==-1)
2679     {
2680       elems->pushBackSilent(0);
2681       return elems.retn();
2682     }
2683   int dim=getSpaceDimension();
2684   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2685   const int* conn      = getNodalConnectivity()->getConstPointer();
2686   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2687   const double* coords = getCoords()->getConstPointer();
2688   int nbOfCells=getNumberOfCells();
2689   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2690     {
2691       for (int i=0; i<dim; i++)
2692         {
2693           elem_bb[i*2]=std::numeric_limits<double>::max();
2694           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2695         }
2696
2697       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2698         {
2699           int node= conn[inode];
2700           if(node>=0)//avoid polyhedron separator
2701             {
2702               for (int idim=0; idim<dim; idim++)
2703                 {
2704                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2705                     {
2706                       elem_bb[idim*2] = coords[node*dim+idim] ;
2707                     }
2708                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2709                     {
2710                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2711                     }
2712                 }
2713             }
2714         }
2715       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2716         elems->pushBackSilent(ielem);
2717     }
2718   return elems.retn();
2719 }
2720
2721 /*!
2722  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2723  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2724  * added in 'elems' parameter.
2725  */
2726 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2727 {
2728   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2729   if(getMeshDimension()==-1)
2730     {
2731       elems->pushBackSilent(0);
2732       return elems.retn();
2733     }
2734   int dim=getSpaceDimension();
2735   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2736   const int* conn      = getNodalConnectivity()->getConstPointer();
2737   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2738   const double* coords = getCoords()->getConstPointer();
2739   int nbOfCells=getNumberOfCells();
2740   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2741     {
2742       for (int i=0; i<dim; i++)
2743         {
2744           elem_bb[i*2]=std::numeric_limits<double>::max();
2745           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2746         }
2747
2748       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2749         {
2750           int node= conn[inode];
2751           if(node>=0)//avoid polyhedron separator
2752             {
2753               for (int idim=0; idim<dim; idim++)
2754                 {
2755                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2756                     {
2757                       elem_bb[idim*2] = coords[node*dim+idim] ;
2758                     }
2759                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2760                     {
2761                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2762                     }
2763                 }
2764             }
2765         }
2766       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2767         elems->pushBackSilent(ielem);
2768     }
2769   return elems.retn();
2770 }
2771
2772 /*!
2773  * Returns a type of a cell by its id.
2774  *  \param [in] cellId - the id of the cell of interest.
2775  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2776  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2777  */
2778 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2779 {
2780   const int *ptI=_nodal_connec_index->getConstPointer();
2781   const int *pt=_nodal_connec->getConstPointer();
2782   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2783     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2784   else
2785     {
2786       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2787       throw INTERP_KERNEL::Exception(oss.str().c_str());
2788     }
2789 }
2790
2791 /*!
2792  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2793  * This method does not throw exception if geometric type \a type is not in \a this.
2794  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2795  * The coordinates array is not considered here.
2796  *
2797  * \param [in] type the geometric type
2798  * \return cell ids in this having geometric type \a type.
2799  */
2800 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2801 {
2802
2803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2804   ret->alloc(0,1);
2805   checkConnectivityFullyDefined();
2806   int nbCells=getNumberOfCells();
2807   int mdim=getMeshDimension();
2808   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2809   if(mdim!=(int)cm.getDimension())
2810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2811   const int *ptI=_nodal_connec_index->getConstPointer();
2812   const int *pt=_nodal_connec->getConstPointer();
2813   for(int i=0;i<nbCells;i++)
2814     {
2815       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2816         ret->pushBackSilent(i);
2817     }
2818   return ret.retn();
2819 }
2820
2821 /*!
2822  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2823  */
2824 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2825 {
2826   const int *ptI=_nodal_connec_index->getConstPointer();
2827   const int *pt=_nodal_connec->getConstPointer();
2828   int nbOfCells=getNumberOfCells();
2829   int ret=0;
2830   for(int i=0;i<nbOfCells;i++)
2831     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2832       ret++;
2833   return ret;
2834 }
2835
2836 /*!
2837  * Returns the nodal connectivity of a given cell.
2838  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2839  * all returned node ids can be used in getCoordinatesOfNode().
2840  *  \param [in] cellId - an id of the cell of interest.
2841  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2842  *         cleared before the appending.
2843  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2844  */
2845 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2846 {
2847   const int *ptI=_nodal_connec_index->getConstPointer();
2848   const int *pt=_nodal_connec->getConstPointer();
2849   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2850     if(*w>=0)
2851       conn.push_back(*w);
2852 }
2853
2854 std::string MEDCouplingUMesh::simpleRepr() const
2855 {
2856   static const char msg0[]="No coordinates specified !";
2857   std::ostringstream ret;
2858   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2859   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2860   int tmpp1,tmpp2;
2861   double tt=getTime(tmpp1,tmpp2);
2862   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2863   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2864   if(_mesh_dim>=-1)
2865     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2866   else
2867     { ret << " Mesh dimension has not been set or is invalid !"; }
2868   if(_coords!=0)
2869     {
2870       const int spaceDim=getSpaceDimension();
2871       ret << spaceDim << "\nInfo attached on space dimension : ";
2872       for(int i=0;i<spaceDim;i++)
2873         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2874       ret << "\n";
2875     }
2876   else
2877     ret << msg0 << "\n";
2878   ret << "Number of nodes : ";
2879   if(_coords!=0)
2880     ret << getNumberOfNodes() << "\n";
2881   else
2882     ret << msg0 << "\n";
2883   ret << "Number of cells : ";
2884   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2885     ret << getNumberOfCells() << "\n";
2886   else
2887     ret << "No connectivity specified !" << "\n";
2888   ret << "Cell types present : ";
2889   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2890     {
2891       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2892       ret << cm.getRepr() << " ";
2893     }
2894   ret << "\n";
2895   return ret.str();
2896 }
2897
2898 std::string MEDCouplingUMesh::advancedRepr() const
2899 {
2900   std::ostringstream ret;
2901   ret << simpleRepr();
2902   ret << "\nCoordinates array : \n___________________\n\n";
2903   if(_coords)
2904     _coords->reprWithoutNameStream(ret);
2905   else
2906     ret << "No array set !\n";
2907   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2908   reprConnectivityOfThisLL(ret);
2909   return ret.str();
2910 }
2911
2912 /*!
2913  * This method returns a C++ code that is a dump of \a this.
2914  * This method will throw if this is not fully defined.
2915  */
2916 std::string MEDCouplingUMesh::cppRepr() const
2917 {
2918   static const char coordsName[]="coords";
2919   static const char connName[]="conn";
2920   static const char connIName[]="connI";
2921   checkFullyDefined();
2922   std::ostringstream ret; ret << "// coordinates" << std::endl;
2923   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2924   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2925   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2926   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2927   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2928   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2929   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2930   return ret.str();
2931 }
2932
2933 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2934 {
2935   std::ostringstream ret;
2936   reprConnectivityOfThisLL(ret);
2937   return ret.str();
2938 }
2939
2940 /*!
2941  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2942  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2943  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2944  * some algos).
2945  * 
2946  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2947  * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
2948  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2949  */
2950 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2951 {
2952   int mdim=getMeshDimension();
2953   if(mdim<0)
2954     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2955   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2957   bool needToCpyCT=true;
2958   if(!_nodal_connec)
2959     {
2960       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2961       needToCpyCT=false;
2962     }
2963   else
2964     {
2965       tmp1=_nodal_connec;
2966       tmp1->incrRef();
2967     }
2968   if(!_nodal_connec_index)
2969     {
2970       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2971       needToCpyCT=false;
2972     }
2973   else
2974     {
2975       tmp2=_nodal_connec_index;
2976       tmp2->incrRef();
2977     }
2978   ret->setConnectivity(tmp1,tmp2,false);
2979   if(needToCpyCT)
2980     ret->_types=_types;
2981   if(!_coords)
2982     {
2983       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2984       ret->setCoords(coords);
2985     }
2986   else
2987     ret->setCoords(_coords);
2988   return ret.retn();
2989 }
2990
2991 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2992 {
2993   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2994     {
2995       int nbOfCells=getNumberOfCells();
2996       const int *c=_nodal_connec->getConstPointer();
2997       const int *ci=_nodal_connec_index->getConstPointer();
2998       for(int i=0;i<nbOfCells;i++)
2999         {
3000           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3001           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3002           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3003           stream << "\n";
3004         }
3005     }
3006   else
3007     stream << "Connectivity not defined !\n";
3008 }
3009
3010 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3011 {
3012   const int *ptI=_nodal_connec_index->getConstPointer();
3013   const int *pt=_nodal_connec->getConstPointer();
3014   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3015     return ptI[cellId+1]-ptI[cellId]-1;
3016   else
3017     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3018 }
3019
3020 /*!
3021  * Returns types of cells of the specified part of \a this mesh.
3022  * This method avoids computing sub-mesh explicitely to get its types.
3023  *  \param [in] begin - an array of cell ids of interest.
3024  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3025  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3026  *         describing the cell types. 
3027  *  \throw If the coordinates array is not set.
3028  *  \throw If the nodal connectivity of cells is not defined.
3029  *  \sa getAllGeoTypes()
3030  */
3031 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3032 {
3033   checkFullyDefined();
3034   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3035   const int *conn=_nodal_connec->getConstPointer();
3036   const int *connIndex=_nodal_connec_index->getConstPointer();
3037   for(const int *w=begin;w!=end;w++)
3038     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3039   return ret;
3040 }
3041
3042 /*!
3043  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3044  * a set of types of cells constituting \a this mesh. 
3045  * This method is for advanced users having prepared their connectivity before. For
3046  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3047  *  \param [in] conn - the nodal connectivity array. 
3048  *  \param [in] connIndex - the nodal connectivity index array.
3049  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3050  *         mesh is updated.
3051  */
3052 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3053 {
3054   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3055   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3056   if(isComputingTypes)
3057     computeTypes();
3058   declareAsNew();
3059 }
3060
3061 /*!
3062  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3063  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3064  */
3065 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3066     _nodal_connec(0),_nodal_connec_index(0),
3067     _types(other._types)
3068 {
3069   if(other._nodal_connec)
3070     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3071   if(other._nodal_connec_index)
3072     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3073 }
3074
3075 MEDCouplingUMesh::~MEDCouplingUMesh()
3076 {
3077   if(_nodal_connec)
3078     _nodal_connec->decrRef();
3079   if(_nodal_connec_index)
3080     _nodal_connec_index->decrRef();
3081 }
3082
3083 /*!
3084  * Recomputes a set of cell types of \a this mesh. For more info see
3085  * \ref MEDCouplingUMeshNodalConnectivity.
3086  */
3087 void MEDCouplingUMesh::computeTypes()
3088 {
3089   if(_nodal_connec && _nodal_connec_index)
3090     {
3091       _types.clear();
3092       const int *conn=_nodal_connec->getConstPointer();
3093       const int *connIndex=_nodal_connec_index->getConstPointer();
3094       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3095       if (nbOfElem > 0)
3096         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3097           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3098     }
3099 }
3100
3101 /*!
3102  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3103  */
3104 void MEDCouplingUMesh::checkFullyDefined() const
3105 {
3106   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3107     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3108 }
3109
3110 /*!
3111  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3112  */
3113 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3114 {
3115   if(!_nodal_connec_index || !_nodal_connec)
3116     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3117 }
3118
3119 /*!
3120  * Returns a number of cells constituting \a this mesh. 
3121  *  \return int - the number of cells in \a this mesh.
3122  *  \throw If the nodal connectivity of cells is not defined.
3123  */
3124 int MEDCouplingUMesh::getNumberOfCells() const
3125
3126   if(_nodal_connec_index)
3127     return _nodal_connec_index->getNumberOfTuples()-1;
3128   else
3129     if(_mesh_dim==-1)
3130       return 1;
3131     else
3132       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3133 }
3134
3135 /*!
3136  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3137  * mesh. For more info see \ref MEDCouplingMeshesPage.
3138  *  \return int - the dimension of \a this mesh.
3139  *  \throw If the mesh dimension is not defined using setMeshDimension().
3140  */
3141 int MEDCouplingUMesh::getMeshDimension() const
3142 {
3143   if(_mesh_dim<-1)
3144     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3145   return _mesh_dim;
3146 }
3147
3148 /*!
3149  * Returns a length of the nodal connectivity array.
3150  * This method is for test reason. Normally the integer returned is not useable by
3151  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3152  *  \return int - the length of the nodal connectivity array.
3153  */
3154 int MEDCouplingUMesh::getMeshLength() const
3155 {
3156   return _nodal_connec->getNbOfElems();
3157 }
3158
3159 /*!
3160  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3161  */
3162 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3163 {
3164   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3165   tinyInfo.push_back(getMeshDimension());
3166   tinyInfo.push_back(getNumberOfCells());
3167   if(_nodal_connec)
3168     tinyInfo.push_back(getMeshLength());
3169   else
3170     tinyInfo.push_back(-1);
3171 }
3172
3173 /*!
3174  * First step of unserialization process.
3175  */
3176 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3177 {
3178   return tinyInfo[6]<=0;
3179 }
3180
3181 /*!
3182  * Second step of serialization process.
3183  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3184  */
3185 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3186 {
3187   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3188   if(tinyInfo[5]!=-1)
3189     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3190 }
3191
3192 /*!
3193  * Third and final step of serialization process.
3194  */
3195 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3196 {
3197   MEDCouplingPointSet::serialize(a1,a2);
3198   if(getMeshDimension()>-1)
3199     {
3200       a1=DataArrayInt::New();
3201       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3202       int *ptA1=a1->getPointer();
3203       const int *conn=getNodalConnectivity()->getConstPointer();
3204       const int *index=getNodalConnectivityIndex()->getConstPointer();
3205       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3206       std::copy(conn,conn+getMeshLength(),ptA1);
3207     }
3208   else
3209     a1=0;
3210 }
3211
3212 /*!
3213  * Second and final unserialization process.
3214  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3215  */
3216 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3217 {
3218   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3219   setMeshDimension(tinyInfo[5]);
3220   if(tinyInfo[7]!=-1)
3221     {
3222       // Connectivity
3223       const int *recvBuffer=a1->getConstPointer();
3224       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3225       myConnecIndex->alloc(tinyInfo[6]+1,1);
3226       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3227       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3228       myConnec->alloc(tinyInfo[7],1);
3229       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3230       setConnectivity(myConnec, myConnecIndex);
3231     }
3232 }
3233
3234 /*!
3235  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3236  * CellIds are given using range specified by a start an end and step.
3237  */
3238 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3239 {
3240   checkFullyDefined();
3241   int ncell=getNumberOfCells();
3242   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3243   ret->_mesh_dim=_mesh_dim;
3244   ret->setCoords(_coords);
3245   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3246   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3247   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3248   int work=start;
3249   const int *conn=_nodal_connec->getConstPointer();
3250   const int *connIndex=_nodal_connec_index->getConstPointer();
3251   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3252     {
3253       if(work>=0 && work<ncell)
3254         {
3255           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3256         }
3257       else
3258         {
3259           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3260           throw INTERP_KERNEL::Exception(oss.str().c_str());
3261         }
3262     }
3263   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3264   int *newConnPtr=newConn->getPointer();
3265   std::set<INTERP_KERNEL::NormalizedCellType> types;
3266   work=start;
3267   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3268     {
3269       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3270       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3271     }
3272   ret->setConnectivity(newConn,newConnI,false);
3273   ret->_types=types;
3274   ret->copyTinyInfoFrom(this);
3275   return ret.retn();
3276 }
3277
3278 /*!
3279  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3280  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3281  * The return newly allocated mesh will share the same coordinates as \a this.
3282  */
3283 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3284 {
3285   checkConnectivityFullyDefined();
3286   int ncell=getNumberOfCells();
3287   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3288   ret->_mesh_dim=_mesh_dim;
3289   ret->setCoords(_coords);
3290   std::size_t nbOfElemsRet=std::distance(begin,end);
3291   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3292   connIndexRet[0]=0;
3293   const int *conn=_nodal_connec->getConstPointer();
3294   const int *connIndex=_nodal_connec_index->getConstPointer();
3295   int newNbring=0;
3296   for(const int *work=begin;work!=end;work++,newNbring++)
3297     {
3298       if(*work>=0 && *work<ncell)
3299         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3300       else
3301         {
3302           free(connIndexRet);
3303           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3304           throw INTERP_KERNEL::Exception(oss.str().c_str());
3305         }
3306     }
3307   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3308   int *connRetWork=connRet;
3309   std::set<INTERP_KERNEL::NormalizedCellType> types;
3310   for(const int *work=begin;work!=end;work++)
3311     {
3312       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3313       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3314     }
3315   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3316   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3318   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3319   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3320   ret->_types=types;
3321   ret->copyTinyInfoFrom(this);
3322   return ret.retn();
3323 }
3324
3325 /*!
3326  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3327  * mesh.<br>
3328  * For 1D cells, the returned field contains lengths.<br>
3329  * For 2D cells, the returned field contains areas.<br>
3330  * For 3D cells, the returned field contains volumes.
3331  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3332  *         orientation, i.e. the volume is always positive.
3333  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3334  *         and one time . The caller is to delete this field using decrRef() as it is no
3335  *         more needed.
3336  */
3337 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3338 {
3339   std::string name="MeasureOfMesh_";
3340   name+=getName();
3341   int nbelem=getNumberOfCells();
3342   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3343   field->setName(name);
3344   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3345   array->alloc(nbelem,1);
3346   double *area_vol=array->getPointer();
3347   field->setArray(array) ; array=0;
3348   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3349   field->synchronizeTimeWithMesh();
3350   if(getMeshDimension()!=-1)
3351     {
3352       int ipt;
3353       INTERP_KERNEL::NormalizedCellType type;
3354       int dim_space=getSpaceDimension();
3355       const double *coords=getCoords()->getConstPointer();
3356       const int *connec=getNodalConnectivity()->getConstPointer();
3357       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3358       for(int iel=0;iel<nbelem;iel++)
3359         {
3360           ipt=connec_index[iel];
3361           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3362           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);
3363         }
3364       if(isAbs)
3365         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3366     }
3367   else
3368     {
3369       area_vol[0]=std::numeric_limits<double>::max();
3370     }
3371   return field.retn();
3372 }
3373
3374 /*!
3375  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3376  * mesh.<br>
3377  * For 1D cells, the returned array contains lengths.<br>
3378  * For 2D cells, the returned array contains areas.<br>
3379  * For 3D cells, the returned array contains volumes.
3380  * This method avoids building explicitly a part of \a this mesh to perform the work.
3381  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3382  *         orientation, i.e. the volume is always positive.
3383  *  \param [in] begin - an array of cell ids of interest.
3384  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3385  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3386  *          delete this array using decrRef() as it is no more needed.
3387  * 
3388  *  \if ENABLE_EXAMPLES
3389  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3390  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3391  *  \endif
3392  *  \sa getMeasureField()
3393  */
3394 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3395 {
3396   std::string name="PartMeasureOfMesh_";
3397   name+=getName();
3398   int nbelem=(int)std::distance(begin,end);
3399   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3400   array->setName(name);
3401   array->alloc(nbelem,1);
3402   double *area_vol=array->getPointer();
3403   if(getMeshDimension()!=-1)
3404     {
3405       int ipt;
3406       INTERP_KERNEL::NormalizedCellType type;
3407       int dim_space=getSpaceDimension();
3408       const double *coords=getCoords()->getConstPointer();
3409       const int *connec=getNodalConnectivity()->getConstPointer();
3410       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3411       for(const int *iel=begin;iel!=end;iel++)
3412         {
3413           ipt=connec_index[*iel];
3414           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3415           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3416         }
3417       if(isAbs)
3418         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3419     }
3420   else
3421     {
3422       area_vol[0]=std::numeric_limits<double>::max();
3423     }
3424   return array.retn();
3425 }
3426
3427 /*!
3428  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3429  * \a this one. The returned field contains the dual cell volume for each corresponding
3430  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3431  *  the dual mesh in P1 sens of \a this.<br>
3432  * For 1D cells, the returned field contains lengths.<br>
3433  * For 2D cells, the returned field contains areas.<br>
3434  * For 3D cells, the returned field contains volumes.
3435  * This method is useful to check "P1*" conservative interpolators.
3436  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3437  *         orientation, i.e. the volume is always positive.
3438  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3439  *          nodes and one time. The caller is to delete this array using decrRef() as
3440  *          it is no more needed.
3441  */
3442 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3443 {
3444   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3445   std::string name="MeasureOnNodeOfMesh_";
3446   name+=getName();
3447   int nbNodes=getNumberOfNodes();
3448   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3449   double cst=1./((double)getMeshDimension()+1.);
3450   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3451   array->alloc(nbNodes,1);
3452   double *valsToFill=array->getPointer();
3453   std::fill(valsToFill,valsToFill+nbNodes,0.);
3454   const double *values=tmp->getArray()->getConstPointer();
3455   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3457   getReverseNodalConnectivity(da,daInd);
3458   const int *daPtr=da->getConstPointer();
3459   const int *daIPtr=daInd->getConstPointer();
3460   for(int i=0;i<nbNodes;i++)
3461     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3462       valsToFill[i]+=cst*values[*cell];
3463   ret->setMesh(this);
3464   ret->setArray(array);
3465   return ret.retn();
3466 }
3467
3468 /*!
3469  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3470  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3471  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3472  * and are normalized.
3473  * <br> \a this can be either 
3474  * - a  2D mesh in 2D or 3D space or 
3475  * - an 1D mesh in 2D space.
3476  * 
3477  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3478  *          cells and one time. The caller is to delete this field using decrRef() as
3479  *          it is no more needed.
3480  *  \throw If the nodal connectivity of cells is not defined.
3481  *  \throw If the coordinates array is not set.
3482  *  \throw If the mesh dimension is not set.
3483  *  \throw If the mesh and space dimension is not as specified above.
3484  */
3485 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3486 {
3487   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3488     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3489   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3490   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3491   int nbOfCells=getNumberOfCells();
3492   int nbComp=getMeshDimension()+1;
3493   array->alloc(nbOfCells,nbComp);
3494   double *vals=array->getPointer();
3495   const int *connI=_nodal_connec_index->getConstPointer();
3496   const int *conn=_nodal_connec->getConstPointer();
3497   const double *coords=_coords->getConstPointer();
3498   if(getMeshDimension()==2)
3499     {
3500       if(getSpaceDimension()==3)
3501         {
3502           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3503           const double *locPtr=loc->getConstPointer();
3504           for(int i=0;i<nbOfCells;i++,vals+=3)
3505             {
3506               int offset=connI[i];
3507               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3508               double n=INTERP_KERNEL::norm<3>(vals);
3509               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3510             }
3511         }
3512       else
3513         {
3514           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3515           const double *isAbsPtr=isAbs->getArray()->begin();
3516           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3517             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3518         }
3519     }
3520   else//meshdimension==1
3521     {
3522       double tmp[2];
3523       for(int i=0;i<nbOfCells;i++)
3524         {
3525           int offset=connI[i];
3526           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3527           double n=INTERP_KERNEL::norm<2>(tmp);
3528           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3529           *vals++=-tmp[1];
3530           *vals++=tmp[0];
3531         }
3532     }
3533   ret->setArray(array);
3534   ret->setMesh(this);
3535   ret->synchronizeTimeWithSupport();
3536   return ret.retn();
3537 }
3538
3539 /*!
3540  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3541  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3542  * and are normalized.
3543  * <br> \a this can be either 
3544  * - a  2D mesh in 2D or 3D space or 
3545  * - an 1D mesh in 2D space.
3546  * 
3547  * This method avoids building explicitly a part of \a this mesh to perform the work.
3548  *  \param [in] begin - an array of cell ids of interest.
3549  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3550  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3551  *          cells and one time. The caller is to delete this field using decrRef() as
3552  *          it is no more needed.
3553  *  \throw If the nodal connectivity of cells is not defined.
3554  *  \throw If the coordinates array is not set.
3555  *  \throw If the mesh dimension is not set.
3556  *  \throw If the mesh and space dimension is not as specified above.
3557  *  \sa buildOrthogonalField()
3558  *
3559  *  \if ENABLE_EXAMPLES
3560  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3561  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3562  *  \endif
3563  */
3564 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3565 {
3566   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3567     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3568   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3569   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3570   std::size_t nbelems=std::distance(begin,end);
3571   int nbComp=getMeshDimension()+1;
3572   array->alloc((int)nbelems,nbComp);
3573   double *vals=array->getPointer();
3574   const int *connI=_nodal_connec_index->getConstPointer();
3575   const int *conn=_nodal_connec->getConstPointer();
3576   const double *coords=_coords->getConstPointer();
3577   if(getMeshDimension()==2)
3578     {
3579       if(getSpaceDimension()==3)
3580         {
3581           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3582           const double *locPtr=loc->getConstPointer();
3583           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3584             {
3585               int offset=connI[*i];
3586               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3587               double n=INTERP_KERNEL::norm<3>(vals);
3588               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3589             }
3590         }
3591       else
3592         {
3593           for(std::size_t i=0;i<nbelems;i++)
3594             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3595         }
3596     }
3597   else//meshdimension==1
3598     {
3599       double tmp[2];
3600       for(const int *i=begin;i!=end;i++)
3601         {
3602           int offset=connI[*i];
3603           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3604           double n=INTERP_KERNEL::norm<2>(tmp);
3605           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3606           *vals++=-tmp[1];
3607           *vals++=tmp[0];
3608         }
3609     }
3610   ret->setArray(array);
3611   ret->setMesh(this);
3612   ret->synchronizeTimeWithSupport();
3613   return ret.retn();
3614 }
3615
3616 /*!
3617  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3618  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3619  * and are \b not normalized.
3620  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3621  *          cells and one time. The caller is to delete this field using decrRef() as
3622  *          it is no more needed.
3623  *  \throw If the nodal connectivity of cells is not defined.
3624  *  \throw If the coordinates array is not set.
3625  *  \throw If \a this->getMeshDimension() != 1.
3626  *  \throw If \a this mesh includes cells of type other than SEG2.
3627  */
3628 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3629 {
3630   if(getMeshDimension()!=1)
3631     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3632   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3633     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3634   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3635   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3636   int nbOfCells=getNumberOfCells();
3637   int spaceDim=getSpaceDimension();
3638   array->alloc(nbOfCells,spaceDim);
3639   double *pt=array->getPointer();
3640   const double *coo=getCoords()->getConstPointer();
3641   std::vector<int> conn;
3642   conn.reserve(2);
3643   for(int i=0;i<nbOfCells;i++)
3644     {
3645       conn.resize(0);
3646       getNodeIdsOfCell(i,conn);
3647       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3648     }
3649   ret->setArray(array);
3650   ret->setMesh(this);
3651   ret->synchronizeTimeWithSupport();
3652   return ret.retn();
3653 }
3654
3655 /*!
3656  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3657  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3658  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3659  * from. If a result face is shared by two 3D cells, then the face in included twice in
3660  * the result mesh.
3661  *  \param [in] origin - 3 components of a point defining location of the plane.
3662  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3663  *         must be greater than 1e-6.
3664  *  \param [in] eps - half-thickness of the plane.
3665  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3666  *         producing correspondent 2D cells. The caller is to delete this array
3667  *         using decrRef() as it is no more needed.
3668  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3669  *         not share the node coordinates array with \a this mesh. The caller is to
3670  *         delete this mesh using decrRef() as it is no more needed.  
3671  *  \throw If the coordinates array is not set.
3672  *  \throw If the nodal connectivity of cells is not defined.
3673  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3674  *  \throw If magnitude of \a vec is less than 1e-6.
3675  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3676  *  \throw If \a this includes quadratic cells.
3677  */
3678 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3679 {
3680   checkFullyDefined();
3681   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3683   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3684   if(candidates->empty())
3685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3686   std::vector<int> nodes;
3687   DataArrayInt *cellIds1D=0;
3688   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3689   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3691   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3692   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3693   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3694   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3695   revDesc2=0; revDescIndx2=0;
3696   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3697   revDesc1=0; revDescIndx1=0;
3698   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3699   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3700   //
3701   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3702   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3703     cut3DCurve[*it]=-1;
3704   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3705   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3706   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3707                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3708                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3709   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3710   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3711   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3712   if(cellIds2->empty())
3713     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3714   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3715   ret->setCoords(mDesc1->getCoords());
3716   ret->setConnectivity(conn,connI,true);
3717   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3718   return ret.retn();
3719 }
3720
3721 /*!
3722  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3723 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3724 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3725 the result mesh.
3726  *  \param [in] origin - 3 components of a point defining location of the plane.
3727  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3728  *         must be greater than 1e-6.
3729  *  \param [in] eps - half-thickness of the plane.
3730  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3731  *         producing correspondent segments. The caller is to delete this array
3732  *         using decrRef() as it is no more needed.
3733  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3734  *         mesh in 3D space. This mesh does not share the node coordinates array with
3735  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3736  *         no more needed. 
3737  *  \throw If the coordinates array is not set.
3738  *  \throw If the nodal connectivity of cells is not defined.
3739  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3740  *  \throw If magnitude of \a vec is less than 1e-6.
3741  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3742  *  \throw If \a this includes quadratic cells.
3743  */
3744 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3745 {
3746   checkFullyDefined();
3747   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3750   if(candidates->empty())
3751     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3752   std::vector<int> nodes;
3753   DataArrayInt *cellIds1D=0;
3754   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3755   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3760   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3761   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3763   //
3764   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3765   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3766     cut3DCurve[*it]=-1;
3767   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3768   int ncellsSub=subMesh->getNumberOfCells();
3769   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3770   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3771                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3772                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3773   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3774   conn->alloc(0,1);
3775   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3776   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3777   for(int i=0;i<ncellsSub;i++)
3778     {
3779       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3780         {
3781           if(cut3DSurf[i].first!=-2)
3782             {
3783               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3784               connI->pushBackSilent(conn->getNumberOfTuples());
3785               cellIds2->pushBackSilent(i);
3786             }
3787           else
3788             {
3789               int cellId3DSurf=cut3DSurf[i].second;
3790               int offset=nodalI[cellId3DSurf]+1;
3791               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3792               for(int j=0;j<nbOfEdges;j++)
3793                 {
3794                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3795                   connI->pushBackSilent(conn->getNumberOfTuples());
3796                   cellIds2->pushBackSilent(cellId3DSurf);
3797                 }
3798             }
3799         }
3800     }
3801   if(cellIds2->empty())
3802     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3803   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3804   ret->setCoords(mDesc1->getCoords());
3805   ret->setConnectivity(conn,connI,true);
3806   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3807   return ret.retn();
3808 }
3809
3810 /*!
3811  * Finds cells whose bounding boxes intersect a given plane.
3812  *  \param [in] origin - 3 components of a point defining location of the plane.
3813  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3814  *         must be greater than 1e-6.
3815  *  \param [in] eps - half-thickness of the plane.
3816  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3817  *         cells. The caller is to delete this array using decrRef() as it is no more
3818  *         needed.
3819  *  \throw If the coordinates array is not set.
3820  *  \throw If the nodal connectivity of cells is not defined.
3821  *  \throw If \a this->getSpaceDimension() != 3.
3822  *  \throw If magnitude of \a vec is less than 1e-6.
3823  *  \sa buildSlice3D()
3824  */
3825 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3826 {
3827   checkFullyDefined();
3828   if(getSpaceDimension()!=3)
3829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3830   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3831   if(normm<1e-6)
3832     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3833   double vec2[3];
3834   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3835   double angle=acos(vec[2]/normm);
3836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3837   double bbox[6];
3838   if(angle>eps)
3839     {
3840       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3841       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3842       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3843       mw->setCoords(coo);
3844       mw->getBoundingBox(bbox);
3845       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3846       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3847     }
3848   else
3849     {
3850       getBoundingBox(bbox);
3851       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3852       cellIds=getCellsInBoundingBox(bbox,eps);
3853     }
3854   return cellIds.retn();
3855 }
3856
3857 /*!
3858  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3859  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3860  * No consideration of coordinate is done by this method.
3861  * 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)
3862  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3863  */
3864 bool MEDCouplingUMesh::isContiguous1D() const
3865 {
3866   if(getMeshDimension()!=1)
3867     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3868   int nbCells=getNumberOfCells();
3869   if(nbCells<1)
3870     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3871   const int *connI=_nodal_connec_index->getConstPointer();
3872   const int *conn=_nodal_connec->getConstPointer();
3873   int ref=conn[connI[0]+2];
3874   for(int i=1;i<nbCells;i++)
3875     {
3876       if(conn[connI[i]+1]!=ref)
3877         return false;
3878       ref=conn[connI[i]+2];
3879     }
3880   return true;
3881 }
3882
3883 /*!
3884  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3885  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3886  * \param pt reference point of the line
3887  * \param v normalized director vector of the line
3888  * \param eps max precision before throwing an exception
3889  * \param res output of size this->getNumberOfCells
3890  */
3891 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3892 {
3893   if(getMeshDimension()!=1)
3894     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3895   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3896     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3897   if(getSpaceDimension()!=3)
3898     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3899   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3900   const double *fPtr=f->getArray()->getConstPointer();
3901   double tmp[3];
3902   for(int i=0;i<getNumberOfCells();i++)
3903     {
3904       const double *tmp1=fPtr+3*i;
3905       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3906       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3907       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3908       double n1=INTERP_KERNEL::norm<3>(tmp);
3909       n1/=INTERP_KERNEL::norm<3>(tmp1);
3910       if(n1>eps)
3911         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3912     }
3913   const double *coo=getCoords()->getConstPointer();
3914   for(int i=0;i<getNumberOfNodes();i++)
3915     {
3916       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3917       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3918       res[i]=std::accumulate(tmp,tmp+3,0.);
3919     }
3920 }
3921
3922 /*!
3923  * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance. 
3924  * \a this is expected to be a mesh so that its space dimension is equal to its
3925  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3926  * 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).
3927  *
3928  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3929  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3930  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3931  *
3932  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3933  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3934  *
3935  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3936  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3937  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3938  * \return the positive value of the distance.
3939  * \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
3940  * dimension - 1.
3941  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3942  */
3943 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3944 {
3945   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3946   if(meshDim!=spaceDim-1)
3947     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3948   if(meshDim!=2 && meshDim!=1)
3949     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3950   checkFullyDefined();
3951   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3952     { 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()); }
3953   DataArrayInt *ret1=0;
3954   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3955   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3957   cellId=*ret1Safe->begin();
3958   return *ret0->begin();
3959 }
3960
3961 /*!
3962  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3963  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3964  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3965  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3966  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3967  * 
3968  * \a this is expected to be a mesh so that its space dimension is equal to its
3969  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3970  * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3971  *
3972  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3973  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3974  *
3975  * \param [in] pts the list of points in which each tuple represents a point
3976  * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
3977  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3978  * \throw if number of components of \a pts is not equal to the space dimension.
3979  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3980  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3981  */
3982 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3983 {
3984   if(!pts)
3985     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3986   pts->checkAllocated();
3987   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3988   if(meshDim!=spaceDim-1)
3989     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3990   if(meshDim!=2 && meshDim!=1)
3991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3992   if(pts->getNumberOfComponents()!=spaceDim)
3993     {
3994       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3995       throw INTERP_KERNEL::Exception(oss.str().c_str());
3996     }
3997   checkFullyDefined();
3998   int nbCells=getNumberOfCells();
3999   if(nbCells==0)
4000     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4001   int nbOfPts=pts->getNumberOfTuples();
4002   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4003   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4004   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4005   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4006   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4007   const double *bbox(bboxArr->begin());
4008   switch(spaceDim)
4009   {
4010     case 3:
4011       {
4012         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4013         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4014           {
4015             double x=std::numeric_limits<double>::max();
4016             std::vector<int> elems;
4017             myTree.getMinDistanceOfMax(ptsPtr,x);
4018             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4019             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4020           }
4021         break;
4022       }
4023     case 2:
4024       {
4025         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4026         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4027           {
4028             double x=std::numeric_limits<double>::max();
4029             std::vector<int> elems;
4030             myTree.getMinDistanceOfMax(ptsPtr,x);
4031             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4032             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4033           }
4034         break;
4035       }
4036     default:
4037       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4038   }
4039   cellIds=ret1.retn();
4040   return ret0.retn();
4041 }
4042
4043 /*!
4044  * \param [in] pt the start pointer (included) of the coordinates of the point
4045  * \param [in] cellIdsBg the start pointer (included) of cellIds
4046  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4047  * \param [in] nc nodal connectivity
4048  * \param [in] ncI nodal connectivity index
4049  * \param [in,out] ret0 the min distance between \a this and the external input point
4050  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4051  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4052  */
4053 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4054 {
4055   cellId=-1;
4056   ret0=std::numeric_limits<double>::max();
4057   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4058     {
4059       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4060       {
4061         case INTERP_KERNEL::NORM_TRI3:
4062           {
4063             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4064             if(tmp<ret0)
4065               { ret0=tmp; cellId=*zeCell; }
4066             break;
4067           }
4068         case INTERP_KERNEL::NORM_QUAD4:
4069         case INTERP_KERNEL::NORM_POLYGON:
4070           {
4071             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4072             if(tmp<ret0)
4073               { ret0=tmp; cellId=*zeCell; }
4074             break;
4075           }
4076         default:
4077           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4078       }
4079     }
4080 }
4081
4082 /*!
4083  * \param [in] pt the start pointer (included) of the coordinates of the point
4084  * \param [in] cellIdsBg the start pointer (included) of cellIds
4085  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4086  * \param [in] nc nodal connectivity
4087  * \param [in] ncI nodal connectivity index
4088  * \param [in,out] ret0 the min distance between \a this and the external input point
4089  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4090  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4091  */
4092 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4093 {
4094   cellId=-1;
4095   ret0=std::numeric_limits<double>::max();
4096   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4097     {
4098       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4099       {
4100         case INTERP_KERNEL::NORM_SEG2:
4101           {
4102             std::size_t uselessEntry=0;
4103             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4104             tmp=sqrt(tmp);
4105             if(tmp<ret0)
4106               { ret0=tmp; cellId=*zeCell; }
4107             break;
4108           }
4109         default:
4110           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4111       }
4112     }
4113 }
4114
4115 /*!
4116  * Finds cells in contact with a ball (i.e. a point with precision). 
4117  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4118  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4119  *
4120  * \warning This method is suitable if the caller intends to evaluate only one
4121  *          point, for more points getCellsContainingPoints() is recommended as it is
4122  *          faster. 
4123  *  \param [in] pos - array of coordinates of the ball central point.
4124  *  \param [in] eps - ball radius.
4125  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4126  *         if there are no such cells.
4127  *  \throw If the coordinates array is not set.
4128  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4129  */
4130 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4131 {
4132   std::vector<int> elts;
4133   getCellsContainingPoint(pos,eps,elts);
4134   if(elts.empty())
4135     return -1;
4136   return elts.front();
4137 }
4138
4139 /*!
4140  * Finds cells in contact with a ball (i.e. a point with precision).
4141  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4142  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4143  * \warning This method is suitable if the caller intends to evaluate only one
4144  *          point, for more points getCellsContainingPoints() is recommended as it is
4145  *          faster. 
4146  *  \param [in] pos - array of coordinates of the ball central point.
4147  *  \param [in] eps - ball radius.
4148  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4149  *         before inserting ids.
4150  *  \throw If the coordinates array is not set.
4151  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4152  *
4153  *  \if ENABLE_EXAMPLES
4154  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4155  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4156  *  \endif
4157  */
4158 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4159 {
4160   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4161   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4162   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4163 }
4164
4165 /// @cond INTERNAL
4166
4167 namespace ParaMEDMEM
4168 {
4169   template<const int SPACEDIMM>
4170   class DummyClsMCUG
4171   {
4172   public:
4173     static const int MY_SPACEDIM=SPACEDIMM;
4174     static const int MY_MESHDIM=8;
4175     typedef int MyConnType;
4176     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4177     // begin
4178     // useless, but for windows compilation ...
4179     const double* getCoordinatesPtr() const { return 0; }
4180     const int* getConnectivityPtr() const { return 0; }
4181     const int* getConnectivityIndexPtr() const { return 0; }
4182     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4183     // end
4184   };
4185
4186
4187
4188   /*!
4189    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4190    */
4191   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4192   {
4193     INTERP_KERNEL::Edge *ret(0);
4194     MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4195     m[n0]=bg[0]; m[n1]=bg[1];
4196     switch(typ)
4197     {
4198       case INTERP_KERNEL::NORM_SEG2:
4199         {
4200           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4201           break;
4202         }
4203       case INTERP_KERNEL::NORM_SEG3:
4204         {
4205           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4206           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4207           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4208           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4209           bool colinearity(inters.areColinears());
4210           delete e1; delete e2;
4211           if(colinearity)
4212             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4213           else
4214             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4215           break;
4216         }
4217       default:
4218         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4219     }
4220     return ret;
4221   }
4222
4223   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4224   {
4225     INTERP_KERNEL::Edge *ret=0;
4226     switch(typ)
4227     {
4228       case INTERP_KERNEL::NORM_SEG2:
4229         {
4230           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4231           break;
4232         }
4233       case INTERP_KERNEL::NORM_SEG3:
4234         {
4235           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4236           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4237           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4238           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4239           bool colinearity=inters.areColinears();
4240           delete e1; delete e2;
4241           if(colinearity)
4242             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4243           else
4244             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4245           mapp2[bg[2]].second=false;
4246           break;
4247         }
4248       default:
4249         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4250     }
4251     return ret;
4252   }
4253
4254   /*!
4255    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4256    * the global mesh 'mDesc'.
4257    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4258    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4259    */
4260   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4261                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4262   {
4263     mapp.clear();
4264     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.
4265     const double *coo=mDesc->getCoords()->getConstPointer();
4266     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4267     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4268     std::set<int> s;
4269     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4270       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4271     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4272       {
4273         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4274         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4275       }
4276     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4277     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4278       {
4279         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4280         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4281       }
4282     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4283       {
4284         if((*it2).second.second)
4285           mapp[(*it2).second.first]=(*it2).first;
4286         ((*it2).second.first)->decrRef();
4287       }
4288     return ret;
4289   }
4290
4291   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4292   {
4293     if(nodeId>=offset2)
4294       {
4295         int locId=nodeId-offset2;
4296         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4297       }
4298     if(nodeId>=offset1)
4299       {
4300         int locId=nodeId-offset1;
4301         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4302       }
4303     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4304   }
4305
4306   /**
4307    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4308    */
4309   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4310                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4311                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4312   {
4313     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4314       {
4315         int eltId1=abs(*desc1)-1;
4316         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4317           {
4318             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4319             if(it==mappRev.end())
4320               {
4321                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4322                 mapp[node]=*it1;
4323                 mappRev[*it1]=node;
4324               }
4325           }
4326       }
4327   }
4328 }
4329
4330 /// @endcond
4331
4332 template<int SPACEDIM>
4333 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4334                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4335 {
4336   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4337   int *eltsIndexPtr(eltsIndex->getPointer());
4338   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4339   const double *bbox(bboxArr->begin());
4340   int nbOfCells=getNumberOfCells();
4341   const int *conn=_nodal_connec->getConstPointer();
4342   const int *connI=_nodal_connec_index->getConstPointer();
4343   double bb[2*SPACEDIM];
4344   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4345   for(int i=0;i<nbOfPoints;i++)
4346     {
4347       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4348       for(int j=0;j<SPACEDIM;j++)
4349         {
4350           bb[2*j]=pos[SPACEDIM*i+j];
4351           bb[2*j+1]=pos[SPACEDIM*i+j];
4352         }
4353       std::vector<int> candidates;
4354       myTree.getIntersectingElems(bb,candidates);
4355       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4356         {
4357           int sz(connI[(*iter)+1]-connI[*iter]-1);
4358           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4359           bool status(false);
4360           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4361             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4362           else
4363             {
4364               if(SPACEDIM!=2)
4365                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4366               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4367               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4368               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4369               INTERP_KERNEL::QuadraticPolygon *pol(0);
4370               for(int j=0;j<sz;j++)
4371                 {
4372                   int nodeId(conn[connI[*iter]+1+j]);
4373                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4374                 }
4375               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4376                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4377               else
4378                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4379               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4380               double a(0.),b(0.),c(0.);
4381               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4382               status=pol->isInOrOut2(n);
4383               delete pol; n->decrRef();
4384             }
4385           if(status)
4386             {
4387               eltsIndexPtr[i+1]++;
4388               elts->pushBackSilent(*iter);
4389             }
4390         }
4391     }
4392 }
4393 /*!
4394  * Finds cells in contact with several balls (i.e. points with precision).
4395  * This method is an extension of getCellContainingPoint() and
4396  * getCellsContainingPoint() for the case of multiple points.
4397  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4398  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4399  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4400  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4401  *         this->getSpaceDimension() * \a nbOfPoints 
4402  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4403  *  \param [in] eps - radius of balls (i.e. the precision).
4404  *  \param [out] elts - vector returning ids of found cells.
4405  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4406  *         dividing cell ids in \a elts into groups each referring to one
4407  *         point. Its every element (except the last one) is an index pointing to the
4408  *         first id of a group of cells. For example cells in contact with the *i*-th
4409  *         point are described by following range of indices:
4410  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4411  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4412  *         Number of cells in contact with the *i*-th point is
4413  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4414  *  \throw If the coordinates array is not set.
4415  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4416  *
4417  *  \if ENABLE_EXAMPLES
4418  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4419  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4420  *  \endif
4421  */
4422 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4423                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4424 {
4425   int spaceDim=getSpaceDimension();
4426   int mDim=getMeshDimension();
4427   if(spaceDim==3)
4428     {
4429       if(mDim==3)
4430         {
4431           const double *coords=_coords->getConstPointer();
4432           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4433         }
4434       /*else if(mDim==2)
4435         {
4436
4437         }*/
4438       else
4439         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4440     }
4441   else if(spaceDim==2)
4442     {
4443       if(mDim==2)
4444         {
4445           const double *coords=_coords->getConstPointer();
4446           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4447         }
4448       else
4449         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4450     }
4451   else if(spaceDim==1)
4452     {
4453       if(mDim==1)
4454         {
4455           const double *coords=_coords->getConstPointer();
4456           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4457         }
4458       else
4459         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4460     }
4461   else
4462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4463 }
4464
4465 /*!
4466  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4467  * least two its edges intersect each other anywhere except their extremities. An
4468  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4469  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4470  *         cleared before filling in.
4471  *  \param [in] eps - precision.
4472  *  \throw If \a this->getMeshDimension() != 2.
4473  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4474  */
4475 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4476 {
4477   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4478   if(getMeshDimension()!=2)
4479     throw INTERP_KERNEL::Exception(msg);
4480   int spaceDim=getSpaceDimension();
4481   if(spaceDim!=2 && spaceDim!=3)
4482     throw INTERP_KERNEL::Exception(msg);
4483   const int *conn=_nodal_connec->getConstPointer();
4484   const int *connI=_nodal_connec_index->getConstPointer();
4485   int nbOfCells=getNumberOfCells();
4486   std::vector<double> cell2DinS2;
4487   for(int i=0;i<nbOfCells;i++)
4488     {
4489       int offset=connI[i];
4490       int nbOfNodesForCell=connI[i+1]-offset-1;
4491       if(nbOfNodesForCell<=3)
4492         continue;
4493       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4494       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4495       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4496         cells.push_back(i);
4497       cell2DinS2.clear();
4498     }
4499 }
4500
4501 /*!
4502  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4503  *
4504  * 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.
4505  * 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.
4506  * 
4507  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4508  * This convex envelop is computed using Jarvis march algorithm.
4509  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4510  * 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)
4511  * 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.
4512  *
4513  * \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.
4514  * \sa MEDCouplingUMesh::colinearize2D
4515  */
4516 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4517 {
4518   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4519     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4520   checkFullyDefined();
4521   const double *coords=getCoords()->getConstPointer();
4522   int nbOfCells=getNumberOfCells();
4523   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4524   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4525   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4526   int *workIndexOut=nodalConnecIndexOut->getPointer();
4527   *workIndexOut=0;
4528   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4529   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4530   std::set<INTERP_KERNEL::NormalizedCellType> types;
4531   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4532   isChanged->alloc(0,1);
4533   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4534     {
4535       int pos=nodalConnecOut->getNumberOfTuples();
4536       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4537         isChanged->pushBackSilent(i);
4538       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4539       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4540     }
4541   if(isChanged->empty())
4542     return 0;
4543   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4544   _types=types;
4545   return isChanged.retn();
4546 }
4547
4548 /*!
4549  * This method is \b NOT const because it can modify \a this.
4550  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4551  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4552  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4553  * \b 1 for translation and rotation around point of 'mesh1D'.
4554  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4555  */
4556 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4557 {
4558   checkFullyDefined();
4559   mesh1D->checkFullyDefined();
4560   if(!mesh1D->isContiguous1D())
4561     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4562   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4563     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4564   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4565     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4566   if(mesh1D->getMeshDimension()!=1)
4567     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4568   bool isQuad=false;
4569   if(isPresenceOfQuadratic())
4570     {
4571       if(mesh1D->isFullyQuadratic())
4572         isQuad=true;
4573       else
4574         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4575     }
4576   zipCoords();
4577   int oldNbOfNodes=getNumberOfNodes();
4578   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4579   switch(policy)
4580   {
4581     case 0:
4582       {
4583         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4584         break;
4585       }
4586     case 1:
4587       {
4588         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4589         break;
4590       }
4591     default:
4592       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4593   }
4594   setCoords(newCoords);
4595   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4596   updateTime();
4597   return ret.retn();
4598 }
4599
4600 /*!
4601  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4602  * If it is not the case an exception will be thrown.
4603  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4604  * intersection of plane defined by ('origin','vec').
4605  * This method has one in/out parameter : 'cut3DCurve'.
4606  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4607  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4608  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4609  * This method will throw an exception if \a this contains a non linear segment.
4610  */
4611 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4612 {
4613   checkFullyDefined();
4614   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4615     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4616   int ncells=getNumberOfCells();
4617   int nnodes=getNumberOfNodes();
4618   double vec2[3],vec3[3],vec4[3];
4619   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4620   if(normm<1e-6)
4621     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4622   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4623   const int *conn=_nodal_connec->getConstPointer();
4624   const int *connI=_nodal_connec_index->getConstPointer();
4625   const double *coo=_coords->getConstPointer();
4626   std::vector<double> addCoo;
4627   for(int i=0;i<ncells;i++)
4628     {
4629       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4630         {
4631           if(cut3DCurve[i]==-2)
4632             {
4633               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4634               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];
4635               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4636               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4637               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4638                 {
4639                   const double *st2=coo+3*st;
4640                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4641                   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]));
4642                   if(pos>eps && pos<1-eps)
4643                     {
4644                       int nNode=((int)addCoo.size())/3;
4645                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4646                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4647                       cut3DCurve[i]=nnodes+nNode;
4648                     }
4649                 }
4650             }
4651         }
4652       else
4653         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4654     }
4655   if(!addCoo.empty())
4656     {
4657       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4658       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4659       coo2->alloc(newNbOfNodes,3);
4660       double *tmp=coo2->getPointer();
4661       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4662       std::copy(addCoo.begin(),addCoo.end(),tmp);
4663       DataArrayDouble::SetArrayIn(coo2,_coords);
4664     }
4665 }
4666
4667 /*!
4668  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4669  * \param mesh1D is the input 1D mesh used for translation computation.
4670  * \return newCoords new coords filled by this method. 
4671  */
4672 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4673 {
4674   int oldNbOfNodes=getNumberOfNodes();
4675   int nbOf1DCells=mesh1D->getNumberOfCells();
4676   int spaceDim=getSpaceDimension();
4677   DataArrayDouble *ret=DataArrayDouble::New();
4678   std::vector<bool> isQuads;
4679   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4680   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4681   double *retPtr=ret->getPointer();
4682   const double *coords=getCoords()->getConstPointer();
4683   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4684   std::vector<int> v;
4685   std::vector<double> c;
4686   double vec[3];
4687   v.reserve(3);
4688   c.reserve(6);
4689   for(int i=0;i<nbOf1DCells;i++)
4690     {
4691       v.resize(0);
4692       mesh1D->getNodeIdsOfCell(i,v);
4693       c.resize(0);
4694       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4695       mesh1D->getCoordinatesOfNode(v[0],c);
4696       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4697       for(int j=0;j<oldNbOfNodes;j++)
4698         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4699       if(isQuad)
4700         {
4701           c.resize(0);
4702           mesh1D->getCoordinatesOfNode(v[1],c);
4703           mesh1D->getCoordinatesOfNode(v[0],c);
4704           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4705           for(int j=0;j<oldNbOfNodes;j++)
4706             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4707         }
4708     }
4709   ret->copyStringInfoFrom(*getCoords());
4710   return ret;
4711 }
4712
4713 /*!
4714  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4715  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4716  * \return newCoords new coords filled by this method. 
4717  */
4718 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4719 {
4720   if(mesh1D->getSpaceDimension()==2)
4721     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4722   if(mesh1D->getSpaceDimension()==3)
4723     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4724   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4725 }
4726
4727 /*!
4728  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4729  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4730  * \return newCoords new coords filled by this method. 
4731  */
4732 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4733 {
4734   if(isQuad)
4735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4736   int oldNbOfNodes=getNumberOfNodes();
4737   int nbOf1DCells=mesh1D->getNumberOfCells();
4738   if(nbOf1DCells<2)
4739     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4740   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4741   int nbOfLevsInVec=nbOf1DCells+1;
4742   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4743   double *retPtr=ret->getPointer();
4744   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4745   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4746   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4747   tmp->setCoords(tmp2);
4748   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4749   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4750   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4751   for(int i=1;i<nbOfLevsInVec;i++)
4752     {
4753       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4754       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4755       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4756       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4757       tmp->translate(vec);
4758       double tmp3[2],radius,alpha,alpha0;
4759       const double *p0=i+1<nbOfLevsInVec?begin:third;
4760       const double *p1=i+1<nbOfLevsInVec?end:begin;
4761       const double *p2=i+1<nbOfLevsInVec?third:end;
4762       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4763       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]);
4764       double angle=acos(cosangle/(radius*radius));
4765       tmp->rotate(end,0,angle);
4766       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4767     }
4768   return ret.retn();
4769 }
4770
4771 /*!
4772  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4773  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4774  * \return newCoords new coords filled by this method. 
4775  */
4776 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4777 {
4778   if(isQuad)
4779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4780   int oldNbOfNodes=getNumberOfNodes();
4781   int nbOf1DCells=mesh1D->getNumberOfCells();
4782   if(nbOf1DCells<2)
4783     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4784   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4785   int nbOfLevsInVec=nbOf1DCells+1;
4786   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4787   double *retPtr=ret->getPointer();
4788   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4789   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4790   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4791   tmp->setCoords(tmp2);
4792   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4793   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4794   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4795   for(int i=1;i<nbOfLevsInVec;i++)
4796     {
4797       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4798       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4799       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4800       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4801       tmp->translate(vec);
4802       double tmp3[2],radius,alpha,alpha0;
4803       const double *p0=i+1<nbOfLevsInVec?begin:third;
4804       const double *p1=i+1<nbOfLevsInVec?end:begin;
4805       const double *p2=i+1<nbOfLevsInVec?third:end;
4806       double vecPlane[3]={
4807         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4808         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4809         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4810       };
4811       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4812       if(norm>1.e-7)
4813         {
4814           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4815           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4816           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4817           double s2=norm2;
4818           double c2=cos(asin(s2));
4819           double m[3][3]={
4820             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4821             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4822             {-vec2[1]*s2, vec2[0]*s2, c2}
4823           };
4824           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]};
4825           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]};
4826           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]};
4827           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4828           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]);
4829           double angle=acos(cosangle/(radius*radius));
4830           tmp->rotate(end,vecPlane,angle);
4831         }
4832       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4833     }
4834   return ret.retn();
4835 }
4836
4837 /*!
4838  * This method is private because not easy to use for end user. This method is const contrary to
4839  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4840  * the coords sorted slice by slice.
4841  * \param isQuad specifies presence of quadratic cells.
4842  */
4843 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4844 {
4845   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4846   int nbOf2DCells=getNumberOfCells();
4847   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4848   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4849   const int *conn=_nodal_connec->getConstPointer();
4850   const int *connI=_nodal_connec_index->getConstPointer();
4851   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4852   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4853   newConnI->alloc(nbOf3DCells+1,1);
4854   int *newConnIPtr=newConnI->getPointer();
4855   *newConnIPtr++=0;
4856   std::vector<int> newc;
4857   for(int j=0;j<nbOf2DCells;j++)
4858     {
4859       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4860       *newConnIPtr++=(int)newc.size();
4861     }
4862   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4863   int *newConnPtr=newConn->getPointer();
4864   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4865   newConnIPtr=newConnI->getPointer();
4866   for(int iz=0;iz<nbOf1DCells;iz++)
4867     {
4868       if(iz!=0)
4869         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4870       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4871         {
4872           int icell=(int)(iter-newc.begin());
4873           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4874             {
4875               if(*iter!=-1)
4876                 *newConnPtr=(*iter)+iz*deltaPerLev;
4877               else
4878                 *newConnPtr=-1;
4879             }
4880           else
4881             *newConnPtr=(*iter);
4882         }
4883     }
4884   ret->setConnectivity(newConn,newConnI,true);
4885   ret->setCoords(getCoords());
4886   return ret;
4887 }
4888
4889 /*!
4890  * Checks if \a this mesh is constituted by only quadratic cells.
4891  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4892  *  \throw If the coordinates array is not set.
4893  *  \throw If the nodal connectivity of cells is not defined.
4894  */
4895 bool MEDCouplingUMesh::isFullyQuadratic() const
4896 {
4897   checkFullyDefined();
4898   bool ret=true;
4899   int nbOfCells=getNumberOfCells();
4900   for(int i=0;i<nbOfCells && ret;i++)
4901     {
4902       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4903       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4904       ret=cm.isQuadratic();
4905     }
4906   return ret;
4907 }
4908
4909 /*!
4910  * Checks if \a this mesh includes any quadratic cell.
4911  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4912  *  \throw If the coordinates array is not set.
4913  *  \throw If the nodal connectivity of cells is not defined.
4914  */
4915 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4916 {
4917   checkFullyDefined();
4918   bool ret=false;
4919   int nbOfCells=getNumberOfCells();
4920   for(int i=0;i<nbOfCells && !ret;i++)
4921     {
4922       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4923       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4924       ret=cm.isQuadratic();
4925     }
4926   return ret;
4927 }
4928
4929 /*!
4930  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4931  * this mesh, it remains unchanged.
4932  *  \throw If the coordinates array is not set.
4933  *  \throw If the nodal connectivity of cells is not defined.
4934  */
4935 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4936 {
4937   checkFullyDefined();
4938   int nbOfCells=getNumberOfCells();
4939   int delta=0;
4940   const int *iciptr=_nodal_connec_index->getConstPointer();
4941   for(int i=0;i<nbOfCells;i++)
4942     {
4943       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4944       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4945       if(cm.isQuadratic())
4946         {
4947           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4948           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4949           if(!cml.isDynamic())
4950             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4951           else
4952             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4953         }
4954     }
4955   if(delta==0)
4956     return ;
4957   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4958   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4959   const int *icptr=_nodal_connec->getConstPointer();
4960   newConn->alloc(getMeshLength()-delta,1);
4961   newConnI->alloc(nbOfCells+1,1);
4962   int *ocptr=newConn->getPointer();
4963   int *ociptr=newConnI->getPointer();
4964   *ociptr=0;
4965   _types.clear();
4966   for(int i=0;i<nbOfCells;i++,ociptr++)
4967     {
4968       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4969       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4970       if(!cm.isQuadratic())
4971         {
4972           _types.insert(type);
4973           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4974           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4975         }
4976       else
4977         {
4978           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4979           _types.insert(typel);
4980           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4981           int newNbOfNodes=cml.getNumberOfNodes();
4982           if(cml.isDynamic())
4983             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4984           *ocptr++=(int)typel;
4985           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4986           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4987         }
4988     }
4989   setConnectivity(newConn,newConnI,false);
4990 }
4991
4992 /*!
4993  * This method converts all linear cell in \a this to quadratic one.
4994  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4995  * 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)
4996  * 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.
4997  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4998  * end of the existing coordinates.
4999  * 
5000  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5001  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5002  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5003  * 
5004  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5005  *
5006  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5007  */
5008 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5009 {
5010   DataArrayInt *conn=0,*connI=0;
5011   DataArrayDouble *coords=0;
5012   std::set<INTERP_KERNEL::NormalizedCellType> types;
5013   checkFullyDefined();
5014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5015   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5016   int meshDim=getMeshDimension();
5017   switch(conversionType)
5018   {
5019     case 0:
5020       switch(meshDim)
5021       {
5022         case 1:
5023           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5024           connSafe=conn; connISafe=connI; coordsSafe=coords;
5025           break;
5026         case 2:
5027           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5028           connSafe=conn; connISafe=connI; coordsSafe=coords;
5029           break;
5030         case 3:
5031           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5032           connSafe=conn; connISafe=connI; coordsSafe=coords;
5033           break;
5034         default:
5035           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5036       }
5037       break;
5038         case 1:
5039           {
5040             switch(meshDim)
5041             {
5042               case 1:
5043                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5044                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5045                 break;
5046               case 2:
5047                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5048                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5049                 break;
5050               case 3:
5051                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5052                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5053                 break;
5054               default:
5055                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5056             }
5057             break;
5058           }
5059         default:
5060           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5061   }
5062   setConnectivity(connSafe,connISafe,false);
5063   _types=types;
5064   setCoords(coordsSafe);
5065   return ret.retn();
5066 }
5067
5068 #if 0
5069 /*!
5070  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5071  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5072  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5073  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5074  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5075  * This method can be seen as the opposite method of colinearize2D.
5076  * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
5077  * to avoid to modify the numbering of existing nodes.
5078  *
5079  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5080  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5081  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5082  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5083  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5084  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5085  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5086  *
5087  * \sa buildDescendingConnectivity2
5088  */
5089 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5090                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5091 {
5092   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5093     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5094   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5095   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5096     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5097   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5098     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5099   //DataArrayInt *out0(0),*outi0(0);
5100   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5101   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5102   //out0s=out0s->buildUnique(); out0s->sort(true);
5103 }
5104 #endif
5105
5106 /*!
5107  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5108  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5109  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5110  */
5111 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5112 {
5113   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5114   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5115   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5116   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5117   int nbOfCells=getNumberOfCells();
5118   int nbOfNodes=getNumberOfNodes();
5119   const int *cPtr=_nodal_connec->getConstPointer();
5120   const int *icPtr=_nodal_connec_index->getConstPointer();
5121   int lastVal=0,offset=nbOfNodes;
5122   for(int i=0;i<nbOfCells;i++,icPtr++)
5123     {
5124       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5125       if(type==INTERP_KERNEL::NORM_SEG2)
5126         {
5127           types.insert(INTERP_KERNEL::NORM_SEG3);
5128           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5129           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5130           newConn->pushBackSilent(offset++);
5131           lastVal+=4;
5132           newConnI->pushBackSilent(lastVal);
5133           ret->pushBackSilent(i);
5134         }
5135       else
5136         {
5137           types.insert(type);
5138           lastVal+=(icPtr[1]-icPtr[0]);
5139           newConnI->pushBackSilent(lastVal);
5140           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5141         }
5142     }
5143   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5144   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5145   return ret.retn();
5146 }
5147
5148 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
5149 {
5150   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5151   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5152   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5153   //
5154   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5155   DataArrayInt *conn1D=0,*conn1DI=0;
5156   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5157   DataArrayDouble *coordsTmp=0;
5158   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5159   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5160   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5161   const int *c1DPtr=conn1D->begin();
5162   const int *c1DIPtr=conn1DI->begin();
5163   int nbOfCells=getNumberOfCells();
5164   const int *cPtr=_nodal_connec->getConstPointer();
5165   const int *icPtr=_nodal_connec_index->getConstPointer();
5166   int lastVal=0;
5167   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5168     {
5169       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5170       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5171       if(!cm.isQuadratic())
5172         {
5173           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5174           types.insert(typ2); newConn->pushBackSilent(typ2);
5175           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5176           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5177             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5178           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5179           newConnI->pushBackSilent(lastVal);
5180           ret->pushBackSilent(i);
5181         }
5182       else
5183         {
5184           types.insert(typ);
5185           lastVal+=(icPtr[1]-icPtr[0]);
5186           newConnI->pushBackSilent(lastVal);
5187           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5188         }
5189     }
5190   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5191   return ret.retn();
5192 }
5193
5194 /*!
5195  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5196  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5197  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5198  */
5199 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5200 {
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5202   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5203   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5204 }
5205
5206 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5207 {
5208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5209   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5210   //
5211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5212   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5214   //
5215   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5216   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5217   DataArrayInt *conn1D=0,*conn1DI=0;
5218   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5219   DataArrayDouble *coordsTmp=0;
5220   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5221   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5223   const int *c1DPtr=conn1D->begin();
5224   const int *c1DIPtr=conn1DI->begin();
5225   int nbOfCells=getNumberOfCells();
5226   const int *cPtr=_nodal_connec->getConstPointer();
5227   const int *icPtr=_nodal_connec_index->getConstPointer();
5228   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5229   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5230     {
5231       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5232       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5233       if(!cm.isQuadratic())
5234         {
5235           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5236           types.insert(typ2); newConn->pushBackSilent(typ2);
5237           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5238           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5239             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5240           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5241           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5242           newConnI->pushBackSilent(lastVal);
5243           ret->pushBackSilent(i);
5244         }
5245       else
5246         {
5247           types.insert(typ);
5248           lastVal+=(icPtr[1]-icPtr[0]);
5249           newConnI->pushBackSilent(lastVal);
5250           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5251         }
5252     }
5253   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5254   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5255   return ret.retn();
5256 }
5257
5258 /*!
5259  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5260  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5261  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5262  */
5263 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5264 {
5265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5266   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5267   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5268 }
5269
5270 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5271 {
5272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5273   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5275   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5276   //
5277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5280   //
5281   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5282   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5283   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5284   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5285   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5287   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5288   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5290   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5292   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5293   int nbOfCells=getNumberOfCells();
5294   const int *cPtr=_nodal_connec->getConstPointer();
5295   const int *icPtr=_nodal_connec_index->getConstPointer();
5296   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5297   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5298     {
5299       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5300       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5301       if(!cm.isQuadratic())
5302         {
5303           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5304           if(typ2==INTERP_KERNEL::NORM_ERROR)
5305             {
5306               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5307               throw INTERP_KERNEL::Exception(oss.str().c_str());
5308             }
5309           types.insert(typ2); newConn->pushBackSilent(typ2);
5310           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5311           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5312             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5313           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5314             {
5315               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5316               int tmpPos=newConn->getNumberOfTuples();
5317               newConn->pushBackSilent(nodeId2);
5318               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5319             }
5320           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5321           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5322           newConnI->pushBackSilent(lastVal);
5323           ret->pushBackSilent(i);
5324         }
5325       else
5326         {
5327           types.insert(typ);
5328           lastVal+=(icPtr[1]-icPtr[0]);
5329           newConnI->pushBackSilent(lastVal);
5330           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5331         }
5332     }
5333   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5335   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5337   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5338   int *c=newConn->getPointer();
5339   const int *cI(newConnI->begin());
5340   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5341     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5342   offset=coordsTmp2Safe->getNumberOfTuples();
5343   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5344     c[cI[(*elt)+1]-1]+=offset;
5345   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5346   return ret.retn();
5347 }
5348
5349 /*!
5350  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5351  * so that the number of cells remains the same. Quadratic faces are converted to
5352  * polygons. This method works only for 2D meshes in
5353  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5354  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5355  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5356  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5357  *         a polylinized edge constituting the input polygon.
5358  *  \throw If the coordinates array is not set.
5359  *  \throw If the nodal connectivity of cells is not defined.
5360  *  \throw If \a this->getMeshDimension() != 2.
5361  *  \throw If \a this->getSpaceDimension() != 2.
5362  */
5363 void MEDCouplingUMesh::tessellate2D(double eps)
5364 {
5365   checkFullyDefined();
5366   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5368   double epsa=fabs(eps);
5369   if(epsa<std::numeric_limits<double>::min())
5370     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 !");
5371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5375   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5376   revDesc1=0; revDescIndx1=0;
5377   mDesc->tessellate2DCurve(eps);
5378   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5379   setCoords(mDesc->getCoords());
5380 }
5381
5382 /*!
5383  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5384  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5385  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5386  *         a sub-divided edge.
5387  *  \throw If the coordinates array is not set.
5388  *  \throw If the nodal connectivity of cells is not defined.
5389  *  \throw If \a this->getMeshDimension() != 1.
5390  *  \throw If \a this->getSpaceDimension() != 2.
5391  */
5392 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5393 {
5394   checkFullyDefined();
5395   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5396     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5397   double epsa=fabs(eps);
5398   if(epsa<std::numeric_limits<double>::min())
5399     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 !");
5400   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5401   int nbCells=getNumberOfCells();
5402   int nbNodes=getNumberOfNodes();
5403   const int *conn=_nodal_connec->getConstPointer();
5404   const int *connI=_nodal_connec_index->getConstPointer();
5405   const double *coords=_coords->getConstPointer();
5406   std::vector<double> addCoo;
5407   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5409   newConnI->alloc(nbCells+1,1);
5410   int *newConnIPtr=newConnI->getPointer();
5411   *newConnIPtr=0;
5412   int tmp1[3];
5413   INTERP_KERNEL::Node *tmp2[3];
5414   std::set<INTERP_KERNEL::NormalizedCellType> types;
5415   for(int i=0;i<nbCells;i++,newConnIPtr++)
5416     {
5417       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5418       if(cm.isQuadratic())
5419         {//assert(connI[i+1]-connI[i]-1==3)
5420           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5421           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5422           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5423           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5424           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5425           if(eac)
5426             {
5427               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5428               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5429               delete eac;
5430               newConnIPtr[1]=(int)newConn.size();
5431             }
5432           else
5433             {
5434               types.insert(INTERP_KERNEL::NORM_SEG2);
5435               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5436               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5437               newConnIPtr[1]=newConnIPtr[0]+3;
5438             }
5439         }
5440       else
5441         {
5442           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5443           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5444           newConnIPtr[1]=newConnIPtr[0]+3;
5445         }
5446     }
5447   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5448     return ;
5449   _types=types;
5450   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5451   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5452   newConnArr->alloc((int)newConn.size(),1);
5453   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5454   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5455   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5456   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5457   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5458   std::copy(addCoo.begin(),addCoo.end(),work);
5459   DataArrayDouble::SetArrayIn(newCoords,_coords);
5460   updateTime();
5461 }
5462
5463 /*!
5464  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5465  * In addition, returns an array mapping new cells to old ones. <br>
5466  * This method typically increases the number of cells in \a this mesh
5467  * but the number of nodes remains \b unchanged.
5468  * That's why the 3D splitting policies
5469  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5470  *  \param [in] policy - specifies a pattern used for splitting.
5471  * The semantic of \a policy is:
5472  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5473  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5474  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5475  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5476  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5477  *          an id of old cell producing it. The caller is to delete this array using
5478  *         decrRef() as it is no more needed. 
5479  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5480  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5481  *          and \a this->getMeshDimension() != 3. 
5482  *  \throw If \a policy is not one of the four discussed above.
5483  *  \throw If the nodal connectivity of cells is not defined.
5484  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5485  */
5486 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5487 {
5488   switch(policy)
5489   {
5490     case 0:
5491       return simplexizePol0();
5492     case 1:
5493       return simplexizePol1();
5494     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5495         return simplexizePlanarFace5();
5496     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5497         return simplexizePlanarFace6();
5498     default:
5499       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)");
5500   }
5501 }
5502
5503 /*!
5504  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5505  * - 1D: INTERP_KERNEL::NORM_SEG2
5506  * - 2D: INTERP_KERNEL::NORM_TRI3
5507  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5508  *
5509  * This method is useful for users that need to use P1 field services as
5510  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5511  * All these methods need mesh support containing only simplex cells.
5512  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5513  *  \throw If the coordinates array is not set.
5514  *  \throw If the nodal connectivity of cells is not defined.
5515  *  \throw If \a this->getMeshDimension() < 1.
5516  */
5517 bool MEDCouplingUMesh::areOnlySimplexCells() const
5518 {
5519   checkFullyDefined();
5520   int mdim=getMeshDimension();
5521   if(mdim<1 || mdim>3)
5522     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5523   int nbCells=getNumberOfCells();
5524   const int *conn=_nodal_connec->getConstPointer();
5525   const int *connI=_nodal_connec_index->getConstPointer();
5526   for(int i=0;i<nbCells;i++)
5527     {
5528       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5529       if(!cm.isSimplex())
5530         return false;
5531     }
5532   return true;
5533 }
5534
5535 /*!
5536  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5537  */
5538 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5539 {
5540   checkConnectivityFullyDefined();
5541   if(getMeshDimension()!=2)
5542     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5543   int nbOfCells=getNumberOfCells();
5544   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5545   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5546   ret->alloc(nbOfCells+nbOfCutCells,1);
5547   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5548   int *retPt=ret->getPointer();
5549   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5550   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5551   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5552   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5553   int *pt=newConn->getPointer();
5554   int *ptI=newConnI->getPointer();
5555   ptI[0]=0;
5556   const int *oldc=_nodal_connec->getConstPointer();
5557   const int *ci=_nodal_connec_index->getConstPointer();
5558   for(int i=0;i<nbOfCells;i++,ci++)
5559     {
5560       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5561         {
5562           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5563             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5564           pt=std::copy(tmp,tmp+8,pt);
5565           ptI[1]=ptI[0]+4;
5566           ptI[2]=ptI[0]+8;
5567           *retPt++=i;
5568           *retPt++=i;
5569           ptI+=2;
5570         }
5571       else
5572         {
5573           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5574           ptI[1]=ptI[0]+ci[1]-ci[0];
5575           ptI++;
5576           *retPt++=i;
5577         }
5578     }
5579   _nodal_connec->decrRef();
5580   _nodal_connec=newConn.retn();
5581   _nodal_connec_index->decrRef();
5582   _nodal_connec_index=newConnI.retn();
5583   computeTypes();
5584   updateTime();
5585   return ret.retn();
5586 }
5587
5588 /*!
5589  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5590  */
5591 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5592 {
5593   checkConnectivityFullyDefined();
5594   if(getMeshDimension()!=2)
5595     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5596   int nbOfCells=getNumberOfCells();
5597   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5598   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5599   ret->alloc(nbOfCells+nbOfCutCells,1);
5600   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5601   int *retPt=ret->getPointer();
5602   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5603   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5604   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5605   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5606   int *pt=newConn->getPointer();
5607   int *ptI=newConnI->getPointer();
5608   ptI[0]=0;
5609   const int *oldc=_nodal_connec->getConstPointer();
5610   const int *ci=_nodal_connec_index->getConstPointer();
5611   for(int i=0;i<nbOfCells;i++,ci++)
5612     {
5613       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5614         {
5615           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5616             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5617           pt=std::copy(tmp,tmp+8,pt);
5618           ptI[1]=ptI[0]+4;
5619           ptI[2]=ptI[0]+8;
5620           *retPt++=i;
5621           *retPt++=i;
5622           ptI+=2;
5623         }
5624       else
5625         {
5626           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5627           ptI[1]=ptI[0]+ci[1]-ci[0];
5628           ptI++;
5629           *retPt++=i;
5630         }
5631     }
5632   _nodal_connec->decrRef();
5633   _nodal_connec=newConn.retn();
5634   _nodal_connec_index->decrRef();
5635   _nodal_connec_index=newConnI.retn();
5636   computeTypes();
5637   updateTime();
5638   return ret.retn();
5639 }
5640
5641 /*!
5642  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5643  */
5644 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5645 {
5646   checkConnectivityFullyDefined();
5647   if(getMeshDimension()!=3)
5648     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5649   int nbOfCells=getNumberOfCells();
5650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5651   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5652   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5653   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5654   int *retPt=ret->getPointer();
5655   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5656   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5657   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5658   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5659   int *pt=newConn->getPointer();
5660   int *ptI=newConnI->getPointer();
5661   ptI[0]=0;
5662   const int *oldc=_nodal_connec->getConstPointer();
5663   const int *ci=_nodal_connec_index->getConstPointer();
5664   for(int i=0;i<nbOfCells;i++,ci++)
5665     {
5666       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5667         {
5668           for(int j=0;j<5;j++,pt+=5,ptI++)
5669             {
5670               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5671               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];
5672               *retPt++=i;
5673               ptI[1]=ptI[0]+5;
5674             }
5675         }
5676       else
5677         {
5678           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5679           ptI[1]=ptI[0]+ci[1]-ci[0];
5680           ptI++;
5681           *retPt++=i;
5682         }
5683     }
5684   _nodal_connec->decrRef();
5685   _nodal_connec=newConn.retn();
5686   _nodal_connec_index->decrRef();
5687   _nodal_connec_index=newConnI.retn();
5688   computeTypes();
5689   updateTime();
5690   return ret.retn();
5691 }
5692
5693 /*!
5694  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5695  */
5696 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5697 {
5698   checkConnectivityFullyDefined();
5699   if(getMeshDimension()!=3)
5700     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5701   int nbOfCells=getNumberOfCells();
5702   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5703   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5704   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5705   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5706   int *retPt=ret->getPointer();
5707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5708   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5709   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5710   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5711   int *pt=newConn->getPointer();
5712   int *ptI=newConnI->getPointer();
5713   ptI[0]=0;
5714   const int *oldc=_nodal_connec->getConstPointer();
5715   const int *ci=_nodal_connec_index->getConstPointer();
5716   for(int i=0;i<nbOfCells;i++,ci++)
5717     {
5718       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5719         {
5720           for(int j=0;j<6;j++,pt+=5,ptI++)
5721             {
5722               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5723               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];
5724               *retPt++=i;
5725               ptI[1]=ptI[0]+5;
5726             }
5727         }
5728       else
5729         {
5730           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5731           ptI[1]=ptI[0]+ci[1]-ci[0];
5732           ptI++;
5733           *retPt++=i;
5734         }
5735     }
5736   _nodal_connec->decrRef();
5737   _nodal_connec=newConn.retn();
5738   _nodal_connec_index->decrRef();
5739   _nodal_connec_index=newConnI.retn();
5740   computeTypes();
5741   updateTime();
5742   return ret.retn();
5743 }
5744
5745 /*!
5746  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5747  * This method completly ignore coordinates.
5748  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5749  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5750  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5751  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5752  */
5753 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5754 {
5755   checkFullyDefined();
5756   if(getMeshDimension()!=2)
5757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5758   int nbOfCells=getNumberOfCells();
5759   int *connI=_nodal_connec_index->getPointer();
5760   int newConnLgth=0;
5761   for(int i=0;i<nbOfCells;i++,connI++)
5762     {
5763       int offset=descIndex[i];
5764       int nbOfEdges=descIndex[i+1]-offset;
5765       //
5766       bool ddirect=desc[offset+nbOfEdges-1]>0;
5767       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5768       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5769       for(int j=0;j<nbOfEdges;j++)
5770         {
5771           bool direct=desc[offset+j]>0;
5772           int edgeId=std::abs(desc[offset+j])-1;
5773           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5774             {
5775               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5776               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5777               int ref2=direct?id1:id2;
5778               if(ref==ref2)
5779                 {
5780                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5781                   newConnLgth+=nbOfSubNodes-1;
5782                   ref=direct?id2:id1;
5783                 }
5784               else
5785                 {
5786                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5787                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5788                 }
5789             }
5790           else
5791             {
5792               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5793             }
5794         }
5795       newConnLgth++;//+1 is for cell type
5796       connI[1]=newConnLgth;
5797     }
5798   //
5799   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5800   newConn->alloc(newConnLgth,1);
5801   int *work=newConn->getPointer();
5802   for(int i=0;i<nbOfCells;i++)
5803     {
5804       *work++=INTERP_KERNEL::NORM_POLYGON;
5805       int offset=descIndex[i];
5806       int nbOfEdges=descIndex[i+1]-offset;
5807       for(int j=0;j<nbOfEdges;j++)
5808         {
5809           bool direct=desc[offset+j]>0;
5810           int edgeId=std::abs(desc[offset+j])-1;
5811           if(direct)
5812             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5813           else
5814             {
5815               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5816               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5817               work=std::copy(it,it+nbOfSubNodes-1,work);
5818             }
5819         }
5820     }
5821   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5822   _types.clear();
5823   if(nbOfCells>0)
5824     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5825 }
5826
5827 /*!
5828  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5829  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5830  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5831  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5832  * so it can be useful to call mergeNodes() before calling this method.
5833  *  \throw If \a this->getMeshDimension() <= 1.
5834  *  \throw If the coordinates array is not set.
5835  *  \throw If the nodal connectivity of cells is not defined.
5836  */
5837 void MEDCouplingUMesh::convertDegeneratedCells()
5838 {
5839   checkFullyDefined();
5840   if(getMeshDimension()<=1)
5841     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5842   int nbOfCells=getNumberOfCells();
5843   if(nbOfCells<1)
5844     return ;
5845   int initMeshLgth=getMeshLength();
5846   int *conn=_nodal_connec->getPointer();
5847   int *index=_nodal_connec_index->getPointer();
5848   int posOfCurCell=0;
5849   int newPos=0;
5850   int lgthOfCurCell;
5851   for(int i=0;i<nbOfCells;i++)
5852     {
5853       lgthOfCurCell=index[i+1]-posOfCurCell;
5854       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5855       int newLgth;
5856       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5857                                                                                                      conn+newPos+1,newLgth);
5858       conn[newPos]=newType;
5859       newPos+=newLgth+1;
5860       posOfCurCell=index[i+1];
5861       index[i+1]=newPos;
5862     }
5863   if(newPos!=initMeshLgth)
5864     _nodal_connec->reAlloc(newPos);
5865   computeTypes();
5866 }
5867
5868 /*!
5869  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5870  * A cell is considered to be oriented correctly if an angle between its
5871  * normal vector and a given vector is less than \c PI / \c 2.
5872  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5873  *         cells. 
5874  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5875  *         checked.
5876  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5877  *         is not cleared before filling in.
5878  *  \throw If \a this->getMeshDimension() != 2.
5879  *  \throw If \a this->getSpaceDimension() != 3.
5880  *
5881  *  \if ENABLE_EXAMPLES
5882  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5883  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5884  *  \endif
5885  */
5886 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5887 {
5888   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5889     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5890   int nbOfCells=getNumberOfCells();
5891   const int *conn=_nodal_connec->getConstPointer();
5892   const int *connI=_nodal_connec_index->getConstPointer();
5893   const double *coordsPtr=_coords->getConstPointer();
5894   for(int i=0;i<nbOfCells;i++)
5895     {
5896       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5897       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5898         {
5899           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5900           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5901             cells.push_back(i);
5902         }
5903     }
5904 }
5905
5906 /*!
5907  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5908  * considered to be oriented correctly if an angle between its normal vector and a
5909  * given vector is less than \c PI / \c 2. 
5910  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5911  *         cells. 
5912  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5913  *         checked.
5914  *  \throw If \a this->getMeshDimension() != 2.
5915  *  \throw If \a this->getSpaceDimension() != 3.
5916  *
5917  *  \if ENABLE_EXAMPLES
5918  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5919  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5920  *  \endif
5921  */
5922 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5923 {
5924   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5925     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5926   int nbOfCells=getNumberOfCells();
5927   int *conn=_nodal_connec->getPointer();
5928   const int *connI=_nodal_connec_index->getConstPointer();
5929   const double *coordsPtr=_coords->getConstPointer();
5930   bool isModified=false;
5931   for(int i=0;i<nbOfCells;i++)
5932     {
5933       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5934       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5935         {
5936           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5937           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5938             {
5939               isModified=true;
5940               if(!isQuadratic)
5941                 {
5942                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5943                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5944                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5945                 }
5946               else
5947                 {
5948                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5949                   std::vector<int> tmp0(sz-1),tmp1(sz);
5950                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5951                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5952                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5953                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5954                 }
5955             }
5956         }
5957     }
5958   if(isModified)
5959     _nodal_connec->declareAsNew();
5960   updateTime();
5961 }
5962
5963 /*!
5964  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5965  * oriented facets. The normal vector of the facet should point out of the cell.
5966  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5967  *         is not cleared before filling in.
5968  *  \throw If \a this->getMeshDimension() != 3.
5969  *  \throw If \a this->getSpaceDimension() != 3.
5970  *  \throw If the coordinates array is not set.
5971  *  \throw If the nodal connectivity of cells is not defined.
5972  *
5973  *  \if ENABLE_EXAMPLES
5974  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5975  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5976  *  \endif
5977  */
5978 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5979 {
5980   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5981     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5982   int nbOfCells=getNumberOfCells();
5983   const int *conn=_nodal_connec->getConstPointer();
5984   const int *connI=_nodal_connec_index->getConstPointer();
5985   const double *coordsPtr=_coords->getConstPointer();
5986   for(int i=0;i<nbOfCells;i++)
5987     {
5988       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5989       if(type==INTERP_KERNEL::NORM_POLYHED)
5990         {
5991           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5992             cells.push_back(i);
5993         }
5994     }
5995 }
5996
5997 /*!
5998  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5999  * out of the cell. 
6000  *  \throw If \a this->getMeshDimension() != 3.
6001  *  \throw If \a this->getSpaceDimension() != 3.
6002  *  \throw If the coordinates array is not set.
6003  *  \throw If the nodal connectivity of cells is not defined.
6004  *  \throw If the reparation fails.
6005  *
6006  *  \if ENABLE_EXAMPLES
6007  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6008  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6009  *  \endif
6010  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6011  */
6012 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6013 {
6014   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6015     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6016   int nbOfCells=getNumberOfCells();
6017   int *conn=_nodal_connec->getPointer();
6018   const int *connI=_nodal_connec_index->getConstPointer();
6019   const double *coordsPtr=_coords->getConstPointer();
6020   for(int i=0;i<nbOfCells;i++)
6021     {
6022       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6023       if(type==INTERP_KERNEL::NORM_POLYHED)
6024         {
6025           try
6026           {
6027               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6028                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6029           }
6030           catch(INTERP_KERNEL::Exception& e)
6031           {
6032               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6033               throw INTERP_KERNEL::Exception(oss.str().c_str());
6034           }
6035         }
6036     }
6037   updateTime();
6038 }
6039
6040 /*!
6041  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6042  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6043  * according to which the first facet of the cell should be oriented to have the normal vector
6044  * pointing out of cell.
6045  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6046  *         cells. The caller is to delete this array using decrRef() as it is no more
6047  *         needed. 
6048  *  \throw If \a this->getMeshDimension() != 3.
6049  *  \throw If \a this->getSpaceDimension() != 3.
6050  *  \throw If the coordinates array is not set.
6051  *  \throw If the nodal connectivity of cells is not defined.
6052  *
6053  *  \if ENABLE_EXAMPLES
6054  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6055  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6056  *  \endif
6057  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6058  */
6059 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6060 {
6061   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6062   if(getMeshDimension()!=3)
6063     throw INTERP_KERNEL::Exception(msg);
6064   int spaceDim=getSpaceDimension();
6065   if(spaceDim!=3)
6066     throw INTERP_KERNEL::Exception(msg);
6067   //
6068   int nbOfCells=getNumberOfCells();
6069   int *conn=_nodal_connec->getPointer();
6070   const int *connI=_nodal_connec_index->getConstPointer();
6071   const double *coo=getCoords()->getConstPointer();
6072   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6073   for(int i=0;i<nbOfCells;i++)
6074     {
6075       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6076       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6077         {
6078           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6079             {
6080               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6081               cells->pushBackSilent(i);
6082             }
6083         }
6084     }
6085   return cells.retn();
6086 }
6087
6088 /*!
6089  * This method is a faster method to correct orientation of all 3D cells in \a this.
6090  * 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.
6091  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6092  * 
6093  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6094  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6095  */
6096 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6097 {
6098   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6099     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6100   int nbOfCells=getNumberOfCells();
6101   int *conn=_nodal_connec->getPointer();
6102   const int *connI=_nodal_connec_index->getConstPointer();
6103   const double *coordsPtr=_coords->getConstPointer();
6104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6105   for(int i=0;i<nbOfCells;i++)
6106     {
6107       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6108       switch(type)
6109       {
6110         case INTERP_KERNEL::NORM_TETRA4:
6111           {
6112             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6113               {
6114                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6115                 ret->pushBackSilent(i);
6116               }
6117             break;
6118           }
6119         case INTERP_KERNEL::NORM_PYRA5:
6120           {
6121             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6122               {
6123                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6124                 ret->pushBackSilent(i);
6125               }
6126             break;
6127           }
6128         case INTERP_KERNEL::NORM_PENTA6:
6129         case INTERP_KERNEL::NORM_HEXA8:
6130         case INTERP_KERNEL::NORM_HEXGP12:
6131           {
6132             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6133               {
6134                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6135                 ret->pushBackSilent(i);
6136               }
6137             break;
6138           }
6139         case INTERP_KERNEL::NORM_POLYHED:
6140           {
6141             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6142               {
6143                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6144                 ret->pushBackSilent(i);
6145               }
6146             break;
6147           }
6148         default:
6149           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 !");
6150       }
6151     }
6152   updateTime();
6153   return ret.retn();
6154 }
6155
6156 /*!
6157  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6158  * If it is not the case an exception will be thrown.
6159  * This method is fast because the first cell of \a this is used to compute the plane.
6160  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6161  * \param pos output of size at least 3 used to store a point owned of searched plane.
6162  */
6163 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6164 {
6165   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6166     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6167   const int *conn=_nodal_connec->getConstPointer();
6168   const int *connI=_nodal_connec_index->getConstPointer();
6169   const double *coordsPtr=_coords->getConstPointer();
6170   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6171   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6172 }
6173
6174 /*!
6175  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6176  * cells. Currently cells of the following types are treated:
6177  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6178  * For a cell of other type an exception is thrown.
6179  * Space dimension of a 2D mesh can be either 2 or 3.
6180  * The Edge Ratio of a cell \f$t\f$ is: 
6181  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6182  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6183  *  the smallest edge lengths of \f$t\f$.
6184  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6185  *          cells and one time, lying on \a this mesh. The caller is to delete this
6186  *          field using decrRef() as it is no more needed. 
6187  *  \throw If the coordinates array is not set.
6188  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6189  *  \throw If the connectivity data array has more than one component.
6190  *  \throw If the connectivity data array has a named component.
6191  *  \throw If the connectivity index data array has more than one component.
6192  *  \throw If the connectivity index data array has a named component.
6193  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6194  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6195  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6196  */
6197 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6198 {
6199   checkCoherency();
6200   int spaceDim=getSpaceDimension();
6201   int meshDim=getMeshDimension();
6202   if(spaceDim!=2 && spaceDim!=3)
6203     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6204   if(meshDim!=2 && meshDim!=3)
6205     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6206   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6207   ret->setMesh(this);
6208   int nbOfCells=getNumberOfCells();
6209   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6210   arr->alloc(nbOfCells,1);
6211   double *pt=arr->getPointer();
6212   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6213   const int *conn=_nodal_connec->getConstPointer();
6214   const int *connI=_nodal_connec_index->getConstPointer();
6215   const double *coo=_coords->getConstPointer();
6216   double tmp[12];
6217   for(int i=0;i<nbOfCells;i++,pt++)
6218     {
6219       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6220       switch(t)
6221       {
6222         case INTERP_KERNEL::NORM_TRI3:
6223           {
6224             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6225             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6226             break;
6227           }
6228         case INTERP_KERNEL::NORM_QUAD4:
6229           {
6230             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6231             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6232             break;
6233           }
6234         case INTERP_KERNEL::NORM_TETRA4:
6235           {
6236             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6237             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6238             break;
6239           }
6240         default:
6241           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6242       }
6243       conn+=connI[i+1]-connI[i];
6244     }
6245   ret->setName("EdgeRatio");
6246   ret->synchronizeTimeWithSupport();
6247   return ret.retn();
6248 }
6249
6250 /*!
6251  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6252  * cells. Currently cells of the following types are treated:
6253  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6254  * For a cell of other type an exception is thrown.
6255  * Space dimension of a 2D mesh can be either 2 or 3.
6256  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6257  *          cells and one time, lying on \a this mesh. The caller is to delete this
6258  *          field using decrRef() as it is no more needed. 
6259  *  \throw If the coordinates array is not set.
6260  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6261  *  \throw If the connectivity data array has more than one component.
6262  *  \throw If the connectivity data array has a named component.
6263  *  \throw If the connectivity index data array has more than one component.
6264  *  \throw If the connectivity index data array has a named component.
6265  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6266  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6267  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6268  */
6269 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6270 {
6271   checkCoherency();
6272   int spaceDim=getSpaceDimension();
6273   int meshDim=getMeshDimension();
6274   if(spaceDim!=2 && spaceDim!=3)
6275     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6276   if(meshDim!=2 && meshDim!=3)
6277     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6278   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6279   ret->setMesh(this);
6280   int nbOfCells=getNumberOfCells();
6281   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6282   arr->alloc(nbOfCells,1);
6283   double *pt=arr->getPointer();
6284   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6285   const int *conn=_nodal_connec->getConstPointer();
6286   const int *connI=_nodal_connec_index->getConstPointer();
6287   const double *coo=_coords->getConstPointer();
6288   double tmp[12];
6289   for(int i=0;i<nbOfCells;i++,pt++)
6290     {
6291       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6292       switch(t)
6293       {
6294         case INTERP_KERNEL::NORM_TRI3:
6295           {
6296             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6297             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6298             break;
6299           }
6300         case INTERP_KERNEL::NORM_QUAD4:
6301           {
6302             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6303             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6304             break;
6305           }
6306         case INTERP_KERNEL::NORM_TETRA4:
6307           {
6308             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6309             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6310             break;
6311           }
6312         default:
6313           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6314       }
6315       conn+=connI[i+1]-connI[i];
6316     }
6317   ret->setName("AspectRatio");
6318   ret->synchronizeTimeWithSupport();
6319   return ret.retn();
6320 }
6321
6322 /*!
6323  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6324  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6325  * treated: INTERP_KERNEL::NORM_QUAD4.
6326  * For a cell of other type an exception is thrown.
6327  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6328  *          cells and one time, lying on \a this mesh. The caller is to delete this
6329  *          field using decrRef() as it is no more needed. 
6330  *  \throw If the coordinates array is not set.
6331  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6332  *  \throw If the connectivity data array has more than one component.
6333  *  \throw If the connectivity data array has a named component.
6334  *  \throw If the connectivity index data array has more than one component.
6335  *  \throw If the connectivity index data array has a named component.
6336  *  \throw If \a this->getMeshDimension() != 2.
6337  *  \throw If \a this->getSpaceDimension() != 3.
6338  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6339  */
6340 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6341 {
6342   checkCoherency();
6343   int spaceDim=getSpaceDimension();
6344   int meshDim=getMeshDimension();
6345   if(spaceDim!=3)
6346     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6347   if(meshDim!=2)
6348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6349   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6350   ret->setMesh(this);
6351   int nbOfCells=getNumberOfCells();
6352   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6353   arr->alloc(nbOfCells,1);
6354   double *pt=arr->getPointer();
6355   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6356   const int *conn=_nodal_connec->getConstPointer();
6357   const int *connI=_nodal_connec_index->getConstPointer();
6358   const double *coo=_coords->getConstPointer();
6359   double tmp[12];
6360   for(int i=0;i<nbOfCells;i++,pt++)
6361     {
6362       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6363       switch(t)
6364       {
6365         case INTERP_KERNEL::NORM_QUAD4:
6366           {
6367             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6368             *pt=INTERP_KERNEL::quadWarp(tmp);
6369             break;
6370           }
6371         default:
6372           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6373       }
6374       conn+=connI[i+1]-connI[i];
6375     }
6376   ret->setName("Warp");
6377   ret->synchronizeTimeWithSupport();
6378   return ret.retn();
6379 }
6380
6381
6382 /*!
6383  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6384  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6385  * treated: INTERP_KERNEL::NORM_QUAD4.
6386  * For a cell of other type an exception is thrown.
6387  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6388  *          cells and one time, lying on \a this mesh. The caller is to delete this
6389  *          field using decrRef() as it is no more needed. 
6390  *  \throw If the coordinates array is not set.
6391  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6392  *  \throw If the connectivity data array has more than one component.
6393  *  \throw If the connectivity data array has a named component.
6394  *  \throw If the connectivity index data array has more than one component.
6395  *  \throw If the connectivity index data array has a named component.
6396  *  \throw If \a this->getMeshDimension() != 2.
6397  *  \throw If \a this->getSpaceDimension() != 3.
6398  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6399  */
6400 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6401 {
6402   checkCoherency();
6403   int spaceDim=getSpaceDimension();
6404   int meshDim=getMeshDimension();
6405   if(spaceDim!=3)
6406     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6407   if(meshDim!=2)
6408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6409   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6410   ret->setMesh(this);
6411   int nbOfCells=getNumberOfCells();
6412   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6413   arr->alloc(nbOfCells,1);
6414   double *pt=arr->getPointer();
6415   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6416   const int *conn=_nodal_connec->getConstPointer();
6417   const int *connI=_nodal_connec_index->getConstPointer();
6418   const double *coo=_coords->getConstPointer();
6419   double tmp[12];
6420   for(int i=0;i<nbOfCells;i++,pt++)
6421     {
6422       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6423       switch(t)
6424       {
6425         case INTERP_KERNEL::NORM_QUAD4:
6426           {
6427             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6428             *pt=INTERP_KERNEL::quadSkew(tmp);
6429             break;
6430           }
6431         default:
6432           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6433       }
6434       conn+=connI[i+1]-connI[i];
6435     }
6436   ret->setName("Skew");
6437   ret->synchronizeTimeWithSupport();
6438   return ret.retn();
6439 }
6440
6441 /*!
6442  * This method aggregate the bbox of each cell and put it into bbox parameter.
6443  * 
6444  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6445  *                         For all other cases this input parameter is ignored.
6446  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6447  * 
6448  * \throw If \a this is not fully set (coordinates and connectivity).
6449  * \throw If a cell in \a this has no valid nodeId.
6450  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6451  */
6452 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6453 {
6454   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6455   if((mDim==3 && sDim==3) || (mDim==2 && sDim==3) || (mDim==1 && sDim==1) || ( mDim==1 && sDim==3))  // Compute refined boundary box for quadratic elements only in 2D.
6456     return getBoundingBoxForBBTreeFast();
6457   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6458     {
6459       bool presenceOfQuadratic(false);
6460       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6461         {
6462           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6463           if(cm.isQuadratic())
6464             presenceOfQuadratic=true;
6465         }
6466       if(!presenceOfQuadratic)
6467         return getBoundingBoxForBBTreeFast();
6468       if(mDim==2 && sDim==2)
6469         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6470       else
6471         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6472     }
6473   throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree : Managed dimensions are (mDim=1,sDim=1), (mDim=1,sDim=2), (mDim=1,sDim=3), (mDim=2,sDim=2), (mDim=2,sDim=3) and (mDim=3,sDim=3) !");
6474 }
6475
6476 /*!
6477  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6478  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6479  * 
6480  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6481  * 
6482  * \throw If \a this is not fully set (coordinates and connectivity).
6483  * \throw If a cell in \a this has no valid nodeId.
6484  */
6485 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6486 {
6487   checkFullyDefined();
6488   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6489   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6490   double *bbox(ret->getPointer());
6491   for(int i=0;i<nbOfCells*spaceDim;i++)
6492     {
6493       bbox[2*i]=std::numeric_limits<double>::max();
6494       bbox[2*i+1]=-std::numeric_limits<double>::max();
6495     }
6496   const double *coordsPtr(_coords->getConstPointer());
6497   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6498   for(int i=0;i<nbOfCells;i++)
6499     {
6500       int offset=connI[i]+1;
6501       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6502       for(int j=0;j<nbOfNodesForCell;j++)
6503         {
6504           int nodeId=conn[offset+j];
6505           if(nodeId>=0 && nodeId<nbOfNodes)
6506             {
6507               for(int k=0;k<spaceDim;k++)
6508                 {
6509                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6510                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6511                 }
6512               kk++;
6513             }
6514         }
6515       if(kk==0)
6516         {
6517           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6518           throw INTERP_KERNEL::Exception(oss.str().c_str());
6519         }
6520     }
6521   return ret.retn();
6522 }
6523
6524 /*!
6525  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6526  * useful for 2D meshes having quadratic cells
6527  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6528  * the two extremities of the arc of circle).
6529  * 
6530  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6531  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6532  * \throw If \a this is not fully defined.
6533  * \throw If \a this is not a mesh with meshDimension equal to 2.
6534  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6535  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6536  */
6537 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6538 {
6539   checkFullyDefined();
6540   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6541   if(spaceDim!=2 || mDim!=2)
6542     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic : This method should be applied on mesh with mesh dimension equal to 2 and space dimension also equal to 2!");
6543   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6544   double *bbox(ret->getPointer());
6545   const double *coords(_coords->getConstPointer());
6546   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6547   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6548     {
6549       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6550       int sz(connI[1]-connI[0]-1);
6551       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6552       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6553       INTERP_KERNEL::QuadraticPolygon *pol(0);
6554       for(int j=0;j<sz;j++)
6555         {
6556           int nodeId(conn[*connI+1+j]);
6557           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6558         }
6559       if(!cm.isQuadratic())
6560         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6561       else
6562         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6563       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6564       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6565     }
6566   return ret.retn();
6567 }
6568
6569 /*!
6570  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6571  * useful for 2D meshes having quadratic cells
6572  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6573  * the two extremities of the arc of circle).
6574  * 
6575  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6576  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6577  * \throw If \a this is not fully defined.
6578  * \throw If \a this is not a mesh with meshDimension equal to 1.
6579  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6580  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6581  */
6582 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6583 {
6584   checkFullyDefined();
6585   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6586   if(spaceDim!=2 || mDim!=1)
6587     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!");
6588   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6589   double *bbox(ret->getPointer());
6590   const double *coords(_coords->getConstPointer());
6591   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6592   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6593     {
6594       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6595       int sz(connI[1]-connI[0]-1);
6596       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6597       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6598       INTERP_KERNEL::Edge *edge(0);
6599       for(int j=0;j<sz;j++)
6600         {
6601           int nodeId(conn[*connI+1+j]);
6602           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6603         }
6604       if(!cm.isQuadratic())
6605         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6606       else
6607         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6608       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6609       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6610     }
6611   return ret.retn();
6612 }
6613
6614 /// @cond INTERNAL
6615
6616 namespace ParaMEDMEMImpl
6617 {
6618   class ConnReader
6619   {
6620   public:
6621     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6622     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6623   private:
6624     const int *_conn;
6625     int _val;
6626   };
6627
6628   class ConnReader2
6629   {
6630   public:
6631     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6632     bool operator() (const int& pos) { return _conn[pos]==_val; }
6633   private:
6634     const int *_conn;
6635     int _val;
6636   };
6637 }
6638
6639 /// @endcond
6640
6641 /*!
6642  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6643  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6644  * \a this is composed in cell types.
6645  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6646  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6647  * This parameter is kept only for compatibility with other methode listed above.
6648  */
6649 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6650 {
6651   checkConnectivityFullyDefined();
6652   const int *conn=_nodal_connec->getConstPointer();
6653   const int *connI=_nodal_connec_index->getConstPointer();
6654   const int *work=connI;
6655   int nbOfCells=getNumberOfCells();
6656   std::size_t n=getAllGeoTypes().size();
6657   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6658   std::set<INTERP_KERNEL::NormalizedCellType> types;
6659   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6660     {
6661       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6662       if(types.find(typ)!=types.end())
6663         {
6664           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6665           oss << " is not contiguous !";
6666           throw INTERP_KERNEL::Exception(oss.str().c_str());
6667         }
6668       types.insert(typ);
6669       ret[3*i]=typ;
6670       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6671       ret[3*i+1]=(int)std::distance(work,work2);
6672       work=work2;
6673     }
6674   return ret;
6675 }
6676
6677 /*!
6678  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6679  * only for types cell, type node is not managed.
6680  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6681  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6682  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6683  * If 2 or more same geometric type is in \a code and exception is thrown too.
6684  *
6685  * This method firstly checks
6686  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6687  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6688  * an exception is thrown too.
6689  * 
6690  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6691  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6692  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6693  */
6694 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6695 {
6696   if(code.empty())
6697     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6698   std::size_t sz=code.size();
6699   std::size_t n=sz/3;
6700   if(sz%3!=0)
6701     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6702   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6703   int nb=0;
6704   bool isNoPflUsed=true;
6705   for(std::size_t i=0;i<n;i++)
6706     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6707       {
6708         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6709         nb+=code[3*i+1];
6710         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6711           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6712         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6713       }
6714   if(types.size()!=n)
6715     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6716   if(isNoPflUsed)
6717     {
6718       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6719         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6720       if(types.size()==_types.size())
6721         return 0;
6722     }
6723   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6724   ret->alloc(nb,1);
6725   int *retPtr=ret->getPointer();
6726   const int *connI=_nodal_connec_index->getConstPointer();
6727   const int *conn=_nodal_connec->getConstPointer();
6728   int nbOfCells=getNumberOfCells();
6729   const int *i=connI;
6730   int kk=0;
6731   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6732     {
6733       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6734       int offset=(int)std::distance(connI,i);
6735       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6736       int nbOfCellsOfCurType=(int)std::distance(i,j);
6737       if(code[3*kk+2]==-1)
6738         for(int k=0;k<nbOfCellsOfCurType;k++)
6739           *retPtr++=k+offset;
6740       else
6741         {
6742           int idInIdsPerType=code[3*kk+2];
6743           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6744             {
6745               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6746               if(zePfl)
6747                 {
6748                   zePfl->checkAllocated();
6749                   if(zePfl->getNumberOfComponents()==1)
6750                     {
6751                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6752                         {
6753                           if(*k>=0 && *k<nbOfCellsOfCurType)
6754                             *retPtr=(*k)+offset;
6755                           else
6756                             {
6757                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6758                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6759                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6760                             }
6761                         }
6762                     }
6763                   else
6764                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6765                 }
6766               else
6767                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6768             }
6769           else
6770             {
6771               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6772               oss << " should be in [0," << idsPerType.size() << ") !";
6773               throw INTERP_KERNEL::Exception(oss.str().c_str());
6774             }
6775         }
6776       i=j;
6777     }
6778   return ret.retn();
6779 }
6780
6781 /*!
6782  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6783  * 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.
6784  * 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.
6785  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6786  * 
6787  * \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.
6788  * \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,
6789  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6790  * \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.
6791  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6792  * \throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if \a this is not fully defined
6793  */
6794 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6795 {
6796   if(!profile)
6797     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6798   if(profile->getNumberOfComponents()!=1)
6799     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6800   checkConnectivityFullyDefined();
6801   const int *conn=_nodal_connec->getConstPointer();
6802   const int *connI=_nodal_connec_index->getConstPointer();
6803   int nbOfCells=getNumberOfCells();
6804   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6805   std::vector<int> typeRangeVals(1);
6806   for(const int *i=connI;i!=connI+nbOfCells;)
6807     {
6808       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6809       if(std::find(types.begin(),types.end(),curType)!=types.end())
6810         {
6811           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6812         }
6813       types.push_back(curType);
6814       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6815       typeRangeVals.push_back((int)std::distance(connI,i));
6816     }
6817   //
6818   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6819   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6823   //
6824   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6825   code.resize(3*nbOfCastsFinal);
6826   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6827   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6828   for(int i=0;i<nbOfCastsFinal;i++)
6829     {
6830       int castId=castsPresent->getIJ(i,0);
6831       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6832       idsInPflPerType2.push_back(tmp3);
6833       code[3*i]=(int)types[castId];
6834       code[3*i+1]=tmp3->getNumberOfTuples();
6835       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6836       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6837         {
6838           tmp4->copyStringInfoFrom(*profile);
6839           idsPerType2.push_back(tmp4);
6840           code[3*i+2]=(int)idsPerType2.size()-1;
6841         }
6842       else
6843         {
6844           code[3*i+2]=-1;
6845         }
6846     }
6847   std::size_t sz2=idsInPflPerType2.size();
6848   idsInPflPerType.resize(sz2);
6849   for(std::size_t i=0;i<sz2;i++)
6850     {
6851       DataArrayInt *locDa=idsInPflPerType2[i];
6852       locDa->incrRef();
6853       idsInPflPerType[i]=locDa;
6854     }
6855   std::size_t sz=idsPerType2.size();
6856   idsPerType.resize(sz);
6857   for(std::size_t i=0;i<sz;i++)
6858     {
6859       DataArrayInt *locDa=idsPerType2[i];
6860       locDa->incrRef();
6861       idsPerType[i]=locDa;
6862     }
6863 }
6864
6865 /*!
6866  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6867  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6868  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6869  * 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.
6870  */
6871 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6872 {
6873   checkFullyDefined();
6874   nM1LevMesh->checkFullyDefined();
6875   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6877   if(_coords!=nM1LevMesh->getCoords())
6878     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6881   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6883   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6884   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6885   tmp->setConnectivity(tmp0,tmp1);
6886   tmp->renumberCells(ret0->getConstPointer(),false);
6887   revDesc=tmp->getNodalConnectivity();
6888   revDescIndx=tmp->getNodalConnectivityIndex();
6889   DataArrayInt *ret=0;
6890   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6891     {
6892       int tmp2;
6893       ret->getMaxValue(tmp2);
6894       ret->decrRef();
6895       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6896       throw INTERP_KERNEL::Exception(oss.str().c_str());
6897     }
6898   nM1LevMeshIds=ret;
6899   //
6900   revDesc->incrRef();
6901   revDescIndx->incrRef();
6902   ret1->incrRef();
6903   ret0->incrRef();
6904   meshnM1Old2New=ret0;
6905   return ret1;
6906 }
6907
6908 /*!
6909  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6910  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6911  * in "Old to New" mode.
6912  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6913  *          this array using decrRef() as it is no more needed.
6914  *  \throw If the nodal connectivity of cells is not defined.
6915  */
6916 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6917 {
6918   checkConnectivityFullyDefined();
6919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6920   renumberCells(ret->getConstPointer(),false);
6921   return ret.retn();
6922 }
6923
6924 /*!
6925  * This methods checks that cells are sorted by their types.
6926  * This method makes asumption (no check) that connectivity is correctly set before calling.
6927  */
6928 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6929 {
6930   checkFullyDefined();
6931   const int *conn=_nodal_connec->getConstPointer();
6932   const int *connI=_nodal_connec_index->getConstPointer();
6933   int nbOfCells=getNumberOfCells();
6934   std::set<INTERP_KERNEL::NormalizedCellType> types;
6935   for(const int *i=connI;i!=connI+nbOfCells;)
6936     {
6937       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6938       if(types.find(curType)!=types.end())
6939         return false;
6940       types.insert(curType);
6941       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6942     }
6943   return true;
6944 }
6945
6946 /*!
6947  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6948  * The geometric type order is specified by MED file.
6949  * 
6950  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6951  */
6952 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6953 {
6954   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6955 }
6956
6957 /*!
6958  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6959  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6960  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6961  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6962  */
6963 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6964 {
6965   checkFullyDefined();
6966   const int *conn=_nodal_connec->getConstPointer();
6967   const int *connI=_nodal_connec_index->getConstPointer();
6968   int nbOfCells=getNumberOfCells();
6969   if(nbOfCells==0)
6970     return true;
6971   int lastPos=-1;
6972   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6973   for(const int *i=connI;i!=connI+nbOfCells;)
6974     {
6975       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6976       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6977       if(isTypeExists!=orderEnd)
6978         {
6979           int pos=(int)std::distance(orderBg,isTypeExists);
6980           if(pos<=lastPos)
6981             return false;
6982           lastPos=pos;
6983           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6984         }
6985       else
6986         {
6987           if(sg.find(curType)==sg.end())
6988             {
6989               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6990               sg.insert(curType);
6991             }
6992           else
6993             return false;
6994         }
6995     }
6996   return true;
6997 }
6998
6999 /*!
7000  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7001  * 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
7002  * 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'.
7003  */
7004 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7005 {
7006   checkConnectivityFullyDefined();
7007   int nbOfCells=getNumberOfCells();
7008   const int *conn=_nodal_connec->getConstPointer();
7009   const int *connI=_nodal_connec_index->getConstPointer();
7010   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7011   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7012   tmpa->alloc(nbOfCells,1);
7013   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7014   tmpb->fillWithZero();
7015   int *tmp=tmpa->getPointer();
7016   int *tmp2=tmpb->getPointer();
7017   for(const int *i=connI;i!=connI+nbOfCells;i++)
7018     {
7019       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7020       if(where!=orderEnd)
7021         {
7022           int pos=(int)std::distance(orderBg,where);
7023           tmp2[pos]++;
7024           tmp[std::distance(connI,i)]=pos;
7025         }
7026       else
7027         {
7028           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7029           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7030           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7031           throw INTERP_KERNEL::Exception(oss.str().c_str());
7032         }
7033     }
7034   nbPerType=tmpb.retn();
7035   return tmpa.retn();
7036 }
7037
7038 /*!
7039  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7040  *
7041  * \return a new object containing the old to new correspondance.
7042  *
7043  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7044  */
7045 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7046 {
7047   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7048 }
7049
7050 /*!
7051  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
7052  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7053  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7054  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7055  */
7056 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7057 {
7058   DataArrayInt *nbPerType=0;
7059   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7060   nbPerType->decrRef();
7061   return tmpa->buildPermArrPerLevel();
7062 }
7063
7064 /*!
7065  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7066  * The number of cells remains unchanged after the call of this method.
7067  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7068  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7069  *
7070  * \return the array giving the correspondance old to new.
7071  */
7072 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7073 {
7074   checkFullyDefined();
7075   computeTypes();
7076   const int *conn=_nodal_connec->getConstPointer();
7077   const int *connI=_nodal_connec_index->getConstPointer();
7078   int nbOfCells=getNumberOfCells();
7079   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7080   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7081     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7082       {
7083         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7084         types.push_back(curType);
7085         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7086       }
7087   DataArrayInt *ret=DataArrayInt::New();
7088   ret->alloc(nbOfCells,1);
7089   int *retPtr=ret->getPointer();
7090   std::fill(retPtr,retPtr+nbOfCells,-1);
7091   int newCellId=0;
7092   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7093     {
7094       for(const int *i=connI;i!=connI+nbOfCells;i++)
7095         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7096           retPtr[std::distance(connI,i)]=newCellId++;
7097     }
7098   renumberCells(retPtr,false);
7099   return ret;
7100 }
7101
7102 /*!
7103  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7104  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7105  * This method makes asumption that connectivity is correctly set before calling.
7106  */
7107 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7108 {
7109   checkConnectivityFullyDefined();
7110   const int *conn=_nodal_connec->getConstPointer();
7111   const int *connI=_nodal_connec_index->getConstPointer();
7112   int nbOfCells=getNumberOfCells();
7113   std::vector<MEDCouplingUMesh *> ret;
7114   for(const int *i=connI;i!=connI+nbOfCells;)
7115     {
7116       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7117       int beginCellId=(int)std::distance(connI,i);
7118       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7119       int endCellId=(int)std::distance(connI,i);
7120       int sz=endCellId-beginCellId;
7121       int *cells=new int[sz];
7122       for(int j=0;j<sz;j++)
7123         cells[j]=beginCellId+j;
7124       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7125       delete [] cells;
7126       ret.push_back(m);
7127     }
7128   return ret;
7129 }
7130
7131 /*!
7132  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7133  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7134  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7135  *
7136  * \return a newly allocated instance, that the caller must manage.
7137  * \throw If \a this contains more than one geometric type.
7138  * \throw If the nodal connectivity of \a this is not fully defined.
7139  * \throw If the internal data is not coherent.
7140  */
7141 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7142 {
7143   checkConnectivityFullyDefined();
7144   if(_types.size()!=1)
7145     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7146   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7147   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7148   ret->setCoords(getCoords());
7149   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7150   if(retC)
7151     {
7152       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7153       retC->setNodalConnectivity(c);
7154     }
7155   else
7156     {
7157       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7158       if(!retD)
7159         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7160       DataArrayInt *c=0,*ci=0;
7161       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7162       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7163       retD->setNodalConnectivity(cs,cis);
7164     }
7165   return ret.retn();
7166 }
7167
7168 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7169 {
7170   checkConnectivityFullyDefined();
7171   if(_types.size()!=1)
7172     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7173   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7174   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7175   if(cm.isDynamic())
7176     {
7177       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7178       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7179       throw INTERP_KERNEL::Exception(oss.str().c_str());
7180     }
7181   int nbCells=getNumberOfCells();
7182   int typi=(int)typ;
7183   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7185   int *outPtr=connOut->getPointer();
7186   const int *conn=_nodal_connec->begin();
7187   const int *connI=_nodal_connec_index->begin();
7188   nbNodesPerCell++;
7189   for(int i=0;i<nbCells;i++,connI++)
7190     {
7191       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7192         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7193       else
7194         {
7195           std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
7196           throw INTERP_KERNEL::Exception(oss.str().c_str());
7197         }
7198     }
7199   return connOut.retn();
7200 }
7201
7202 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7203 {
7204   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7205   checkConnectivityFullyDefined();
7206   if(_types.size()!=1)
7207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7208   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7209   if(lgth<nbCells)
7210     throw INTERP_KERNEL::Exception(msg0);
7211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7212   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7213   int *cp(c->getPointer()),*cip(ci->getPointer());
7214   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7215   cip[0]=0;
7216   for(int i=0;i<nbCells;i++,cip++,incip++)
7217     {
7218       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7219       int delta(stop-strt);
7220       if(delta>=1)
7221         {
7222           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7223             cp=std::copy(incp+strt,incp+stop,cp);
7224           else
7225             throw INTERP_KERNEL::Exception(msg0);
7226         }
7227       else
7228         throw INTERP_KERNEL::Exception(msg0);
7229       cip[1]=cip[0]+delta;
7230     }
7231   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7232 }
7233
7234 /*!
7235  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7236  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7237  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7238  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7239  * are not used here to avoid the build of big permutation array.
7240  *
7241  * \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
7242  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7243  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7244  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7245  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7246  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7247  * \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
7248  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7249  */
7250 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7251                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7252                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7253 {
7254   std::vector<const MEDCouplingUMesh *> ms2;
7255   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7256     if(*it)
7257       {
7258         (*it)->checkConnectivityFullyDefined();
7259         ms2.push_back(*it);
7260       }
7261   if(ms2.empty())
7262     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7263   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7264   int meshDim=ms2[0]->getMeshDimension();
7265   std::vector<const MEDCouplingUMesh *> m1ssm;
7266   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7267   //
7268   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7269   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7270   int fake=0,rk=0;
7271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7272   ret1->alloc(0,1); ret2->alloc(0,1);
7273   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7274     {
7275       if(meshDim!=(*it)->getMeshDimension())
7276         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7277       if(refCoo!=(*it)->getCoords())
7278         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7279       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7280       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7281       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7282       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7283         {
7284           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7285           m1ssmSingleAuto.push_back(singleCell);
7286           m1ssmSingle.push_back(singleCell);
7287           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7288         }
7289     }
7290   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7292   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7293   for(std::size_t i=0;i<m1ssm.size();i++)
7294     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7295   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7296   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7297   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7298   return ret0.retn();
7299 }
7300
7301 /*!
7302  * This method returns a newly created DataArrayInt instance.
7303  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7304  */
7305 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7306 {
7307   checkFullyDefined();
7308   const int *conn=_nodal_connec->getConstPointer();
7309   const int *connIndex=_nodal_connec_index->getConstPointer();
7310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7311   for(const int *w=begin;w!=end;w++)
7312     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7313       ret->pushBackSilent(*w);
7314   return ret.retn();
7315 }
7316
7317 /*!
7318  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7319  * are in [0:getNumberOfCells())
7320  */
7321 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7322 {
7323   checkFullyDefined();
7324   const int *conn=_nodal_connec->getConstPointer();
7325   const int *connI=_nodal_connec_index->getConstPointer();
7326   int nbOfCells=getNumberOfCells();
7327   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7328   int *tmp=new int[nbOfCells];
7329   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7330     {
7331       int j=0;
7332       for(const int *i=connI;i!=connI+nbOfCells;i++)
7333         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7334           tmp[std::distance(connI,i)]=j++;
7335     }
7336   DataArrayInt *ret=DataArrayInt::New();
7337   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7338   ret->copyStringInfoFrom(*da);
7339   int *retPtr=ret->getPointer();
7340   const int *daPtr=da->getConstPointer();
7341   int nbOfElems=da->getNbOfElems();
7342   for(int k=0;k<nbOfElems;k++)
7343     retPtr[k]=tmp[daPtr[k]];
7344   delete [] tmp;
7345   return ret;
7346 }
7347
7348 /*!
7349  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7350  * This method \b works \b for mesh sorted by type.
7351  * cells whose ids is in 'idsPerGeoType' array.
7352  * This method conserves coords and name of mesh.
7353  */
7354 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7355 {
7356   std::vector<int> code=getDistributionOfTypes();
7357   std::size_t nOfTypesInThis=code.size()/3;
7358   int sz=0,szOfType=0;
7359   for(std::size_t i=0;i<nOfTypesInThis;i++)
7360     {
7361       if(code[3*i]!=type)
7362         sz+=code[3*i+1];
7363       else
7364         szOfType=code[3*i+1];
7365     }
7366   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7367     if(*work<0 || *work>=szOfType)
7368       {
7369         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7370         oss << ". It should be in [0," << szOfType << ") !";
7371         throw INTERP_KERNEL::Exception(oss.str().c_str());
7372       }
7373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7374   int *idsPtr=idsTokeep->getPointer();
7375   int offset=0;
7376   for(std::size_t i=0;i<nOfTypesInThis;i++)
7377     {
7378       if(code[3*i]!=type)
7379         for(int j=0;j<code[3*i+1];j++)
7380           *idsPtr++=offset+j;
7381       else
7382         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7383       offset+=code[3*i+1];
7384     }
7385   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7386   ret->copyTinyInfoFrom(this);
7387   return ret.retn();
7388 }
7389
7390 /*!
7391  * This method returns a vector of size 'this->getNumberOfCells()'.
7392  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7393  */
7394 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7395 {
7396   int ncell=getNumberOfCells();
7397   std::vector<bool> ret(ncell);
7398   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7399   const int *c=getNodalConnectivity()->getConstPointer();
7400   for(int i=0;i<ncell;i++)
7401     {
7402       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7403       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7404       ret[i]=cm.isQuadratic();
7405     }
7406   return ret;
7407 }
7408
7409 /*!
7410  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7411  */
7412 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7413 {
7414   if(other->getType()!=UNSTRUCTURED)
7415     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7416   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7417   return MergeUMeshes(this,otherC);
7418 }
7419
7420 /*!
7421  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7422  * computed by averaging coordinates of cell nodes, so this method is not a right
7423  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7424  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7425  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7426  *          components. The caller is to delete this array using decrRef() as it is
7427  *          no more needed.
7428  *  \throw If the coordinates array is not set.
7429  *  \throw If the nodal connectivity of cells is not defined.
7430  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7431  */
7432 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7433 {
7434   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7435   int spaceDim=getSpaceDimension();
7436   int nbOfCells=getNumberOfCells();
7437   ret->alloc(nbOfCells,spaceDim);
7438   ret->copyStringInfoFrom(*getCoords());
7439   double *ptToFill=ret->getPointer();
7440   const int *nodal=_nodal_connec->getConstPointer();
7441   const int *nodalI=_nodal_connec_index->getConstPointer();
7442   const double *coor=_coords->getConstPointer();
7443   for(int i=0;i<nbOfCells;i++)
7444     {
7445       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7446       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7447       ptToFill+=spaceDim;
7448     }
7449   return ret.retn();
7450 }
7451
7452 /*!
7453  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7454  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7455  * 
7456  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7457  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7458  * 
7459  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7460  * \throw If \a this is not fully defined (coordinates and connectivity)
7461  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7462  */
7463 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7464 {
7465   checkFullyDefined();
7466   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7467   int spaceDim=getSpaceDimension();
7468   int nbOfCells=getNumberOfCells();
7469   int nbOfNodes=getNumberOfNodes();
7470   ret->alloc(nbOfCells,spaceDim);
7471   double *ptToFill=ret->getPointer();
7472   const int *nodal=_nodal_connec->getConstPointer();
7473   const int *nodalI=_nodal_connec_index->getConstPointer();
7474   const double *coor=_coords->getConstPointer();
7475   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7476     {
7477       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7478       std::fill(ptToFill,ptToFill+spaceDim,0.);
7479       if(type!=INTERP_KERNEL::NORM_POLYHED)
7480         {
7481           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7482             {
7483               if(*conn>=0 && *conn<nbOfNodes)
7484                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7485               else
7486                 {
7487                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7488                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7489                 }
7490             }
7491           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7492           if(nbOfNodesInCell>0)
7493             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7494           else
7495             {
7496               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7497               throw INTERP_KERNEL::Exception(oss.str().c_str());
7498             }
7499         }
7500       else
7501         {
7502           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7503           s.erase(-1);
7504           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7505             {
7506               if(*it>=0 && *it<nbOfNodes)
7507                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7508               else
7509                 {
7510                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7511                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7512                 }
7513             }
7514           if(!s.empty())
7515             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7516           else
7517             {
7518               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7519               throw INTERP_KERNEL::Exception(oss.str().c_str());
7520             }
7521         }
7522     }
7523   return ret.retn();
7524 }
7525
7526 /*!
7527  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7528  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7529  * are specified via an array of cell ids. 
7530  *  \warning Validity of the specified cell ids is not checked! 
7531  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7532  *  \param [in] begin - an array of cell ids of interest.
7533  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7534  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7535  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7536  *          caller is to delete this array using decrRef() as it is no more needed. 
7537  *  \throw If the coordinates array is not set.
7538  *  \throw If the nodal connectivity of cells is not defined.
7539  *
7540  *  \if ENABLE_EXAMPLES
7541  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7542  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7543  *  \endif
7544  */
7545 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7546 {
7547   DataArrayDouble *ret=DataArrayDouble::New();
7548   int spaceDim=getSpaceDimension();
7549   int nbOfTuple=(int)std::distance(begin,end);
7550   ret->alloc(nbOfTuple,spaceDim);
7551   double *ptToFill=ret->getPointer();
7552   double *tmp=new double[spaceDim];
7553   const int *nodal=_nodal_connec->getConstPointer();
7554   const int *nodalI=_nodal_connec_index->getConstPointer();
7555   const double *coor=_coords->getConstPointer();
7556   for(const int *w=begin;w!=end;w++)
7557     {
7558       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7559       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7560       ptToFill+=spaceDim;
7561     }
7562   delete [] tmp;
7563   return ret;
7564 }
7565
7566 /*!
7567  * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
7568  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7569  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7570  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7571  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7572  * 
7573  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7574  * \throw If spaceDim!=3 or meshDim!=2.
7575  * \throw If connectivity of \a this is invalid.
7576  * \throw If connectivity of a cell in \a this points to an invalid node.
7577  */
7578 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7579 {
7580   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7581   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7582   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7583     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7584   ret->alloc(nbOfCells,4);
7585   double *retPtr(ret->getPointer());
7586   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7587   const double *coor(_coords->begin());
7588   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7589     {
7590       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7591       if(nodalI[1]-nodalI[0]>=3)
7592         {
7593           for(int j=0;j<3;j++)
7594             {
7595               int nodeId(nodal[nodalI[0]+1+j]);
7596               if(nodeId>=0 && nodeId<nbOfNodes)
7597                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7598               else
7599                 {
7600                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7601                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7602                 }
7603             }
7604         }
7605       else
7606         {
7607           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7608           throw INTERP_KERNEL::Exception(oss.str().c_str());
7609         }
7610       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7611       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7612     }
7613   return ret.retn();
7614 }
7615
7616 /*!
7617  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7618  * 
7619  */
7620 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7621 {
7622   if(!da)
7623     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7624   da->checkAllocated();
7625   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7626   ret->setCoords(da);
7627   int nbOfTuples=da->getNumberOfTuples();
7628   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7630   c->alloc(2*nbOfTuples,1);
7631   cI->alloc(nbOfTuples+1,1);
7632   int *cp=c->getPointer();
7633   int *cip=cI->getPointer();
7634   *cip++=0;
7635   for(int i=0;i<nbOfTuples;i++)
7636     {
7637       *cp++=INTERP_KERNEL::NORM_POINT1;
7638       *cp++=i;
7639       *cip++=2*(i+1);
7640     }
7641   ret->setConnectivity(c,cI,true);
7642   return ret.retn();
7643 }
7644 /*!
7645  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7646  * Cells and nodes of
7647  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7648  *  \param [in] mesh1 - the first mesh.
7649  *  \param [in] mesh2 - the second mesh.
7650  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7651  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7652  *          is no more needed.
7653  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7654  *  \throw If the coordinates array is not set in none of the meshes.
7655  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7656  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7657  */
7658 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7659 {
7660   std::vector<const MEDCouplingUMesh *> tmp(2);
7661   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7662   return MergeUMeshes(tmp);
7663 }
7664
7665 /*!
7666  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7667  * Cells and nodes of
7668  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7669  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7670  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7671  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7672  *          is no more needed.
7673  *  \throw If \a a.size() == 0.
7674  *  \throw If \a a[ *i* ] == NULL.
7675  *  \throw If the coordinates array is not set in none of the meshes.
7676  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7677  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7678  */
7679 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7680 {
7681   std::size_t sz=a.size();
7682   if(sz==0)
7683     return MergeUMeshesLL(a);
7684   for(std::size_t ii=0;ii<sz;ii++)
7685     if(!a[ii])
7686       {
7687         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7688         throw INTERP_KERNEL::Exception(oss.str().c_str());
7689       }
7690   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7691   std::vector< const MEDCouplingUMesh * > aa(sz);
7692   int spaceDim=-3;
7693   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7694     {
7695       const MEDCouplingUMesh *cur=a[i];
7696       const DataArrayDouble *coo=cur->getCoords();
7697       if(coo)
7698         spaceDim=coo->getNumberOfComponents();
7699     }
7700   if(spaceDim==-3)
7701     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7702   for(std::size_t i=0;i<sz;i++)
7703     {
7704       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7705       aa[i]=bb[i];
7706     }
7707   return MergeUMeshesLL(aa);
7708 }
7709
7710 /// @cond INTERNAL
7711
7712 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7713 {
7714   if(a.empty())
7715     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7716   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7717   int meshDim=(*it)->getMeshDimension();
7718   int nbOfCells=(*it)->getNumberOfCells();
7719   int meshLgth=(*it++)->getMeshLength();
7720   for(;it!=a.end();it++)
7721     {
7722       if(meshDim!=(*it)->getMeshDimension())
7723         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7724       nbOfCells+=(*it)->getNumberOfCells();
7725       meshLgth+=(*it)->getMeshLength();
7726     }
7727   std::vector<const MEDCouplingPointSet *> aps(a.size());
7728   std::copy(a.begin(),a.end(),aps.begin());
7729   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7730   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7731   ret->setCoords(pts);
7732   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7733   c->alloc(meshLgth,1);
7734   int *cPtr=c->getPointer();
7735   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7736   cI->alloc(nbOfCells+1,1);
7737   int *cIPtr=cI->getPointer();
7738   *cIPtr++=0;
7739   int offset=0;
7740   int offset2=0;
7741   for(it=a.begin();it!=a.end();it++)
7742     {
7743       int curNbOfCell=(*it)->getNumberOfCells();
7744       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7745       const int *curC=(*it)->_nodal_connec->getConstPointer();
7746       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7747       for(int j=0;j<curNbOfCell;j++)
7748         {
7749           const int *src=curC+curCI[j];
7750           *cPtr++=*src++;
7751           for(;src!=curC+curCI[j+1];src++,cPtr++)
7752             {
7753               if(*src!=-1)
7754                 *cPtr=*src+offset2;
7755               else
7756                 *cPtr=-1;
7757             }
7758         }
7759       offset+=curCI[curNbOfCell];
7760       offset2+=(*it)->getNumberOfNodes();
7761     }
7762   //
7763   ret->setConnectivity(c,cI,true);
7764   return ret.retn();
7765 }
7766
7767 /// @endcond
7768
7769 /*!
7770  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7771  * dimension and sharing the node coordinates array.
7772  * All cells of the first mesh precede all cells of the second mesh
7773  * within the result mesh. 
7774  *  \param [in] mesh1 - the first mesh.
7775  *  \param [in] mesh2 - the second mesh.
7776  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7777  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7778  *          is no more needed.
7779  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7780  *  \throw If the meshes do not share the node coordinates array.
7781  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7782  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7783  */
7784 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7785 {
7786   std::vector<const MEDCouplingUMesh *> tmp(2);
7787   tmp[0]=mesh1; tmp[1]=mesh2;
7788   return MergeUMeshesOnSameCoords(tmp);
7789 }
7790
7791 /*!
7792  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7793  * dimension and sharing the node coordinates array.
7794  * All cells of the *i*-th mesh precede all cells of the
7795  * (*i*+1)-th mesh within the result mesh.
7796  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7797  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7798  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7799  *          is no more needed.
7800  *  \throw If \a a.size() == 0.
7801  *  \throw If \a a[ *i* ] == NULL.
7802  *  \throw If the meshes do not share the node coordinates array.
7803  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7804  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7805  */
7806 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7807 {
7808   if(meshes.empty())
7809     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7810   for(std::size_t ii=0;ii<meshes.size();ii++)
7811     if(!meshes[ii])
7812       {
7813         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7814         throw INTERP_KERNEL::Exception(oss.str().c_str());
7815       }
7816   const DataArrayDouble *coords=meshes.front()->getCoords();
7817   int meshDim=meshes.front()->getMeshDimension();
7818   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7819   int meshLgth=0;
7820   int meshIndexLgth=0;
7821   for(;iter!=meshes.end();iter++)
7822     {
7823       if(coords!=(*iter)->getCoords())
7824         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7825       if(meshDim!=(*iter)->getMeshDimension())
7826         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7827       meshLgth+=(*iter)->getMeshLength();
7828       meshIndexLgth+=(*iter)->getNumberOfCells();
7829     }
7830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7831   nodal->alloc(meshLgth,1);
7832   int *nodalPtr=nodal->getPointer();
7833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7834   nodalIndex->alloc(meshIndexLgth+1,1);
7835   int *nodalIndexPtr=nodalIndex->getPointer();
7836   int offset=0;
7837   for(iter=meshes.begin();iter!=meshes.end();iter++)
7838     {
7839       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7840       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7841       int nbOfCells=(*iter)->getNumberOfCells();
7842       int meshLgth2=(*iter)->getMeshLength();
7843       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7844       if(iter!=meshes.begin())
7845         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7846       else
7847         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7848       offset+=meshLgth2;
7849     }
7850   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7851   ret->setName("merge");
7852   ret->setMeshDimension(meshDim);
7853   ret->setConnectivity(nodal,nodalIndex,true);
7854   ret->setCoords(coords);
7855   return ret;
7856 }
7857
7858 /*!
7859  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7860  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7861  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7862  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7863  * New" mode are returned for each input mesh.
7864  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7865  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7866  *          valid values [0,1,2], see zipConnectivityTraducer().
7867  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7868  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7869  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7870  *          no more needed.
7871  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7872  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7873  *          is no more needed.
7874  *  \throw If \a meshes.size() == 0.
7875  *  \throw If \a meshes[ *i* ] == NULL.
7876  *  \throw If the meshes do not share the node coordinates array.
7877  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7878  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7879  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7880  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7881  */
7882 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7883 {
7884   //All checks are delegated to MergeUMeshesOnSameCoords
7885   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7887   corr.resize(meshes.size());
7888   std::size_t nbOfMeshes=meshes.size();
7889   int offset=0;
7890   const int *o2nPtr=o2n->getConstPointer();
7891   for(std::size_t i=0;i<nbOfMeshes;i++)
7892     {
7893       DataArrayInt *tmp=DataArrayInt::New();
7894       int curNbOfCells=meshes[i]->getNumberOfCells();
7895       tmp->alloc(curNbOfCells,1);
7896       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7897       offset+=curNbOfCells;
7898       tmp->setName(meshes[i]->getName());
7899       corr[i]=tmp;
7900     }
7901   return ret.retn();
7902 }
7903
7904 /*!
7905  * Makes all given meshes share the nodal connectivity array. The common connectivity
7906  * array is created by concatenating the connectivity arrays of all given meshes. All
7907  * the given meshes must be of the same space dimension but dimension of cells **can
7908  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7909  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7910  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7911  *  \param [in,out] meshes - a vector of meshes to update.
7912  *  \throw If any of \a meshes is NULL.
7913  *  \throw If the coordinates array is not set in any of \a meshes.
7914  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7915  *  \throw If \a meshes are of different space dimension.
7916  */
7917 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7918 {
7919   std::size_t sz=meshes.size();
7920   if(sz==0 || sz==1)
7921     return;
7922   std::vector< const DataArrayDouble * > coords(meshes.size());
7923   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7924   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7925     {
7926       if((*it))
7927         {
7928           (*it)->checkConnectivityFullyDefined();
7929           const DataArrayDouble *coo=(*it)->getCoords();
7930           if(coo)
7931             *it2=coo;
7932           else
7933             {
7934               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7935               oss << " has no coordinate array defined !";
7936               throw INTERP_KERNEL::Exception(oss.str().c_str());
7937             }
7938         }
7939       else
7940         {
7941           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7942           oss << " is null !";
7943           throw INTERP_KERNEL::Exception(oss.str().c_str());
7944         }
7945     }
7946   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7947   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7948   int offset=(*it)->getNumberOfNodes();
7949   (*it++)->setCoords(res);
7950   for(;it!=meshes.end();it++)
7951     {
7952       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7953       (*it)->setCoords(res);
7954       (*it)->shiftNodeNumbersInConn(offset);
7955       offset+=oldNumberOfNodes;
7956     }
7957 }
7958
7959 /*!
7960  * Merges nodes coincident with a given precision within all given meshes that share
7961  * the nodal connectivity array. The given meshes **can be of different** mesh
7962  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7963  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7964  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7965  *  \param [in,out] meshes - a vector of meshes to update.
7966  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7967  *  \throw If any of \a meshes is NULL.
7968  *  \throw If the \a meshes do not share the same node coordinates array.
7969  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7970  */
7971 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7972 {
7973   if(meshes.empty())
7974     return ;
7975   std::set<const DataArrayDouble *> s;
7976   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7977     {
7978       if(*it)
7979         s.insert((*it)->getCoords());
7980       else
7981         {
7982           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 !";
7983           throw INTERP_KERNEL::Exception(oss.str().c_str());
7984         }
7985     }
7986   if(s.size()!=1)
7987     {
7988       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 !";
7989       throw INTERP_KERNEL::Exception(oss.str().c_str());
7990     }
7991   const DataArrayDouble *coo=*(s.begin());
7992   if(!coo)
7993     return;
7994   //
7995   DataArrayInt *comm,*commI;
7996   coo->findCommonTuples(eps,-1,comm,commI);
7997   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7998   int oldNbOfNodes=coo->getNumberOfTuples();
7999   int newNbOfNodes;
8000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8001   if(oldNbOfNodes==newNbOfNodes)
8002     return ;
8003   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8004   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8005     {
8006       (*it)->renumberNodesInConn(o2n->getConstPointer());
8007       (*it)->setCoords(newCoords);
8008     } 
8009 }
8010
8011 /*!
8012  * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [ \a connBg , \a connEnd ) and returns its extruded cell by inserting the result at the end of ret.
8013  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8014  * \param isQuad specifies the policy of connectivity.
8015  * @ret in/out parameter in which the result will be append
8016  */
8017 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8018 {
8019   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8020   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8021   ret.push_back(cm.getExtrudedType());
8022   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8023   switch(flatType)
8024   {
8025     case INTERP_KERNEL::NORM_POINT1:
8026       {
8027         ret.push_back(connBg[1]);
8028         ret.push_back(connBg[1]+nbOfNodesPerLev);
8029         break;
8030       }
8031     case INTERP_KERNEL::NORM_SEG2:
8032       {
8033         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8034         ret.insert(ret.end(),conn,conn+4);
8035         break;
8036       }
8037     case INTERP_KERNEL::NORM_SEG3:
8038       {
8039         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8040         ret.insert(ret.end(),conn,conn+8);
8041         break;
8042       }
8043     case INTERP_KERNEL::NORM_QUAD4:
8044       {
8045         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8046         ret.insert(ret.end(),conn,conn+8);
8047         break;
8048       }
8049     case INTERP_KERNEL::NORM_TRI3:
8050       {
8051         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8052         ret.insert(ret.end(),conn,conn+6);
8053         break;
8054       }
8055     case INTERP_KERNEL::NORM_TRI6:
8056       {
8057         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,
8058           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8059         ret.insert(ret.end(),conn,conn+15);
8060         break;
8061       }
8062     case INTERP_KERNEL::NORM_QUAD8:
8063       {
8064         int conn[20]={
8065           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8066           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8067           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8068         };
8069         ret.insert(ret.end(),conn,conn+20);
8070         break;
8071       }
8072     case INTERP_KERNEL::NORM_POLYGON:
8073       {
8074         std::back_insert_iterator< std::vector<int> > ii(ret);
8075         std::copy(connBg+1,connEnd,ii);
8076         *ii++=-1;
8077         std::reverse_iterator<const int *> rConnBg(connEnd);
8078         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8079         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8080         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8081         for(std::size_t i=0;i<nbOfRadFaces;i++)
8082           {
8083             *ii++=-1;
8084             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8085             std::copy(conn,conn+4,ii);
8086           }
8087         break;
8088       }
8089     default:
8090       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8091   }
8092 }
8093
8094 /*!
8095  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8096  */
8097 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8098 {
8099   std::size_t i, ip1;
8100   double v[3]={0.,0.,0.};
8101   std::size_t sz=std::distance(begin,end);
8102   if(isQuadratic)
8103     sz/=2;
8104   for(i=0;i<sz;i++)
8105     {
8106       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];
8107       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8108       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8109     }
8110   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8111
8112   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8113   // SEG3 forming a circle):
8114   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8115     {
8116       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8117       for(std::size_t j=0;j<sz;j++)
8118         {
8119           if (j%2)  // current point i is quadratic, next point i+1 is standard
8120             {
8121               i = sz+j;
8122               ip1 = (j+1)%sz; // ip1 = "i+1"
8123             }
8124           else      // current point i is standard, next point i+1 is quadratic
8125             {
8126               i = j;
8127               ip1 = j+sz;
8128             }
8129           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8130           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8131           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8132         }
8133       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8134     }
8135   return (ret>0.);
8136 }
8137
8138 /*!
8139  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8140  */
8141 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8142 {
8143   std::vector<std::pair<int,int> > edges;
8144   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8145   const int *bgFace=begin;
8146   for(std::size_t i=0;i<nbOfFaces;i++)
8147     {
8148       const int *endFace=std::find(bgFace+1,end,-1);
8149       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8150       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8151         {
8152           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8153           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8154             return false;
8155           edges.push_back(p1);
8156         }
8157       bgFace=endFace+1;
8158     }
8159   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8160 }
8161
8162 /*!
8163  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8164  */
8165 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8166 {
8167   double vec0[3],vec1[3];
8168   std::size_t sz=std::distance(begin,end);
8169   if(sz%2!=0)
8170     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8171   int nbOfNodes=(int)sz/2;
8172   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8173   const double *pt0=coords+3*begin[0];
8174   const double *pt1=coords+3*begin[nbOfNodes];
8175   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8176   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8177 }
8178
8179 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8180 {
8181   std::size_t sz=std::distance(begin,end);
8182   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8183   std::size_t nbOfNodes(sz/2);
8184   std::copy(begin,end,(int *)tmp);
8185   for(std::size_t j=1;j<nbOfNodes;j++)
8186     {
8187       begin[j]=tmp[nbOfNodes-j];
8188       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8189     }
8190 }
8191
8192 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8193 {
8194   std::size_t sz=std::distance(begin,end);
8195   if(sz!=4)
8196     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8197   double vec0[3],vec1[3];
8198   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8199   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]; 
8200   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;
8201 }
8202
8203 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8204 {
8205   std::size_t sz=std::distance(begin,end);
8206   if(sz!=5)
8207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8208   double vec0[3];
8209   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8210   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8211   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8212 }
8213
8214 /*!
8215  * 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 ) 
8216  * 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
8217  * a 2D space.
8218  *
8219  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8220  * \param [in] coords the coordinates with nb of components exactly equal to 3
8221  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8222  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8223  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8224  */
8225 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8226 {
8227   int nbFaces=std::count(begin+1,end,-1)+1;
8228   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8229   double *vPtr=v->getPointer();
8230   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8231   double *pPtr=p->getPointer();
8232   const int *stFaceConn=begin+1;
8233   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8234     {
8235       const int *endFaceConn=std::find(stFaceConn,end,-1);
8236       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8237       stFaceConn=endFaceConn+1;
8238     }
8239   pPtr=p->getPointer(); vPtr=v->getPointer();
8240   DataArrayInt *comm1=0,*commI1=0;
8241   v->findCommonTuples(eps,-1,comm1,commI1);
8242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8243   const int *comm1Ptr=comm1->getConstPointer();
8244   const int *commI1Ptr=commI1->getConstPointer();
8245   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8246   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8247   //
8248   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8249   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8250   mm->finishInsertingCells();
8251   //
8252   for(int i=0;i<nbOfGrps1;i++)
8253     {
8254       int vecId=comm1Ptr[commI1Ptr[i]];
8255       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8256       DataArrayInt *comm2=0,*commI2=0;
8257       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8258       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8259       const int *comm2Ptr=comm2->getConstPointer();
8260       const int *commI2Ptr=commI2->getConstPointer();
8261       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8262       for(int j=0;j<nbOfGrps2;j++)
8263         {
8264           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8265             {
8266               res->insertAtTheEnd(begin,end);
8267               res->pushBackSilent(-1);
8268             }
8269           else
8270             {
8271               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8272               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8273               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8274               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8275               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8276               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8277               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8278               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8279               const int *idsNodePtr=idsNode->getConstPointer();
8280               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];
8281               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8282               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8283               if(std::abs(norm)>eps)
8284                 {
8285                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8286                   mm3->rotate(center,vec,angle);
8287                 }
8288               mm3->changeSpaceDimension(2);
8289               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8290               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8291               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8292               int nbOfCells=mm4->getNumberOfCells();
8293               for(int k=0;k<nbOfCells;k++)
8294                 {
8295                   int l=0;
8296                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8297                     res->pushBackSilent(idsNodePtr[*work]);
8298                   res->pushBackSilent(-1);
8299                 }
8300             }
8301         }
8302     }
8303   res->popBackSilent();
8304 }
8305
8306 /*!
8307  * 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
8308  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8309  * 
8310  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8311  * \param [in] coords coordinates expected to have 3 components.
8312  * \param [in] begin start of the nodal connectivity of the face.
8313  * \param [in] end end of the nodal connectivity (excluded) of the face.
8314  * \param [out] v the normalized vector of size 3
8315  * \param [out] p the pos of plane
8316  */
8317 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8318 {
8319   std::size_t nbPoints=std::distance(begin,end);
8320   if(nbPoints<3)
8321     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8322   double vec[3]={0.,0.,0.};
8323   std::size_t j=0;
8324   bool refFound=false;
8325   for(;j<nbPoints-1 && !refFound;j++)
8326     {
8327       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8328       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8329       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8330       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8331       if(norm>eps)
8332         {
8333           refFound=true;
8334           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8335         }
8336     }
8337   for(std::size_t i=j;i<nbPoints-1;i++)
8338     {
8339       double curVec[3];
8340       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8341       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8342       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8343       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8344       if(norm<eps)
8345         continue;
8346       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8347       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];
8348       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8349       if(norm>eps)
8350         {
8351           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8352           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8353           return ;
8354         }
8355     }
8356   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8357 }
8358
8359 /*!
8360  * This method tries to obtain a well oriented polyhedron.
8361  * If the algorithm fails, an exception will be thrown.
8362  */
8363 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8364 {
8365   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8366   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8367   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8368   isPerm[0]=true;
8369   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8370   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8371   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8372   //
8373   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8374     {
8375       bgFace=begin;
8376       std::size_t smthChanged=0;
8377       for(std::size_t i=0;i<nbOfFaces;i++)
8378         {
8379           endFace=std::find(bgFace+1,end,-1);
8380           nbOfEdgesInFace=std::distance(bgFace,endFace);
8381           if(!isPerm[i])
8382             {
8383               bool b;
8384               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8385                 {
8386                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8387                   std::pair<int,int> p2(p1.second,p1.first);
8388                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8389                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8390                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8391                 }
8392               if(isPerm[i])
8393                 { 
8394                   if(!b)
8395                     std::reverse(bgFace+1,endFace);
8396                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8397                     {
8398                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8399                       std::pair<int,int> p2(p1.second,p1.first);
8400                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8401                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8402                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8403                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8404                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8405                       if(it!=edgesOK.end())
8406                         {
8407                           edgesOK.erase(it);
8408                           edgesFinished.push_back(p1);
8409                         }
8410                       else
8411                         edgesOK.push_back(p1);
8412                     }
8413                 }
8414             }
8415           bgFace=endFace+1;
8416         }
8417       if(smthChanged==0)
8418         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8419     }
8420   if(!edgesOK.empty())
8421     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8422   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8423     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8424       bgFace=begin;
8425       for(std::size_t i=0;i<nbOfFaces;i++)
8426         {
8427           endFace=std::find(bgFace+1,end,-1);
8428           std::reverse(bgFace+1,endFace);
8429           bgFace=endFace+1;
8430         }
8431     }
8432 }
8433
8434 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8435 {
8436   int nbOfNodesExpected(skin->getNumberOfNodes());
8437   const int *n2oPtr(n2o->getConstPointer());
8438   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8439   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8440   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8441   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8442   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8443   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8444   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8445   if(nbOfNodesExpected<1)
8446     return ret.retn();
8447   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8448   *work++=n2oPtr[prevNode];
8449   for(int i=1;i<nbOfNodesExpected;i++)
8450     {
8451       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8452         {
8453           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8454           conn.erase(prevNode);
8455           if(conn.size()==1)
8456             {
8457               int curNode(*(conn.begin()));
8458               *work++=n2oPtr[curNode];
8459               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8460               shar.erase(prevCell);
8461               if(shar.size()==1)
8462                 {
8463                   prevCell=*(shar.begin());
8464                   prevNode=curNode;
8465                 }
8466               else
8467                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8468             }
8469           else
8470             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8471         }
8472       else
8473         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8474     }
8475   return ret.retn();
8476 }
8477
8478 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8479 {
8480   int nbOfNodesExpected(skin->getNumberOfNodes());
8481   int nbOfTurn(nbOfNodesExpected/2);
8482   const int *n2oPtr(n2o->getConstPointer());
8483   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8484   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8485   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8486   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8487   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8488   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8489   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8490   if(nbOfNodesExpected<1)
8491     return ret.retn();
8492   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8493   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8494   for(int i=1;i<nbOfTurn;i++)
8495     {
8496       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8497         {
8498           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8499           conn.erase(prevNode);
8500           if(conn.size()==1)
8501             {
8502               int curNode(*(conn.begin()));
8503               *work=n2oPtr[curNode];
8504               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8505               shar.erase(prevCell);
8506               if(shar.size()==1)
8507                 {
8508                   int curCell(*(shar.begin()));
8509                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8510                   prevCell=curCell;
8511                   prevNode=curNode;
8512                   work++;
8513                 }
8514               else
8515                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8516             }
8517           else
8518             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8519         }
8520       else
8521         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8522     }
8523   return ret.retn();
8524 }
8525
8526 /*!
8527  * This method makes the assumption spacedimension == meshdimension == 2.
8528  * This method works only for linear cells.
8529  * 
8530  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8531  */
8532 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8533 {
8534   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8536   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8537   int oldNbOfNodes(skin->getNumberOfNodes());
8538   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8539   int nbOfNodesExpected(skin->getNumberOfNodes());
8540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8541   int nbCells(skin->getNumberOfCells());
8542   if(nbCells==nbOfNodesExpected)
8543     return buildUnionOf2DMeshLinear(skin,n2o);
8544   else if(2*nbCells==nbOfNodesExpected)
8545     return buildUnionOf2DMeshQuadratic(skin,n2o);
8546   else
8547     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8548 }
8549
8550 /*!
8551  * This method makes the assumption spacedimension == meshdimension == 3.
8552  * This method works only for linear cells.
8553  * 
8554  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8555  */
8556 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8557 {
8558   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8560   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8561   const int *conn=m->getNodalConnectivity()->getConstPointer();
8562   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8563   int nbOfCells=m->getNumberOfCells();
8564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8565   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8566   if(nbOfCells<1)
8567     return ret.retn();
8568   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8569   for(int i=1;i<nbOfCells;i++)
8570     {
8571       *work++=-1;
8572       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8573     }
8574   return ret.retn();
8575 }
8576
8577 /*!
8578  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8579  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8580  */
8581 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8582 {
8583   double *w=zipFrmt;
8584   if(spaceDim==3)
8585     for(int i=0;i<nbOfNodesInCell;i++)
8586       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8587   else if(spaceDim==2)
8588     {
8589       for(int i=0;i<nbOfNodesInCell;i++)
8590         {
8591           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8592           *w++=0.;
8593         }
8594     }
8595   else
8596     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8597 }
8598
8599 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8600 {
8601   int nbOfCells=getNumberOfCells();
8602   if(nbOfCells<=0)
8603     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8604   static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,36,4};
8605   ofs << "  <" << getVTKDataSetType() << ">\n";
8606   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8607   ofs << "      <PointData>\n" << pointData << std::endl;
8608   ofs << "      </PointData>\n";
8609   ofs << "      <CellData>\n" << cellData << std::endl;
8610   ofs << "      </CellData>\n";
8611   ofs << "      <Points>\n";
8612   if(getSpaceDimension()==3)
8613     _coords->writeVTK(ofs,8,"Points",byteData);
8614   else
8615     {
8616       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8617       coo->writeVTK(ofs,8,"Points",byteData);
8618     }
8619   ofs << "      </Points>\n";
8620   ofs << "      <Cells>\n";
8621   const int *cPtr=_nodal_connec->getConstPointer();
8622   const int *cIPtr=_nodal_connec_index->getConstPointer();
8623   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8624   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8625   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8626   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8627   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8628   int szFaceOffsets=0,szConn=0;
8629   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8630     {
8631       *w2=cPtr[cIPtr[i]];
8632       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8633         {
8634           *w1=-1;
8635           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8636           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8637         }
8638       else
8639         {
8640           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8641           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8642           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8643           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8644           w4=std::copy(c.begin(),c.end(),w4);
8645         }
8646     }
8647   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8648   types->writeVTK(ofs,8,"UInt8","types",byteData);
8649   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8650   if(szFaceOffsets!=0)
8651     {//presence of Polyhedra
8652       connectivity->reAlloc(szConn);
8653       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8654       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8655       w1=faces->getPointer();
8656       for(int i=0;i<nbOfCells;i++)
8657         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8658           {
8659             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8660             *w1++=nbFaces;
8661             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8662             for(int j=0;j<nbFaces;j++)
8663               {
8664                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8665                 *w1++=(int)std::distance(w6,w5);
8666                 w1=std::copy(w6,w5,w1);
8667                 w6=w5+1;
8668               }
8669           }
8670       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8671     }
8672   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8673   ofs << "      </Cells>\n";
8674   ofs << "    </Piece>\n";
8675   ofs << "  </" << getVTKDataSetType() << ">\n";
8676 }
8677
8678 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8679 {
8680   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8681   if(_mesh_dim==-2)
8682     { stream << " Not set !"; return ; }
8683   stream << " Mesh dimension : " << _mesh_dim << ".";
8684   if(_mesh_dim==-1)
8685     return ;
8686   if(!_coords)
8687     { stream << " No coordinates set !"; return ; }
8688   if(!_coords->isAllocated())
8689     { stream << " Coordinates set but not allocated !"; return ; }
8690   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8691   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8692   if(!_nodal_connec_index)
8693     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8694   if(!_nodal_connec_index->isAllocated())
8695     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8696   int lgth=_nodal_connec_index->getNumberOfTuples();
8697   int cpt=_nodal_connec_index->getNumberOfComponents();
8698   if(cpt!=1 || lgth<1)
8699     return ;
8700   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8701 }
8702
8703 std::string MEDCouplingUMesh::getVTKDataSetType() const
8704 {
8705   return std::string("UnstructuredGrid");
8706 }
8707
8708 std::string MEDCouplingUMesh::getVTKFileExtension() const
8709 {
8710   return std::string("vtu");
8711 }
8712
8713 /*!
8714  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8715  * returns a result mesh constituted by polygons.
8716  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8717  * all nodes from m2.
8718  * The meshes should be in 2D space. In
8719  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8720  * meshes.
8721  *  \param [in] m1 - the first input mesh which is a partitioned object. The mesh must be so that each point in the space covered by \a m1
8722  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8723  *  \param [in] m2 - the second input mesh which is a partition tool. The mesh must be so that each point in the space covered by \a m2
8724  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8725  *  \param [in] eps - precision used to detect coincident mesh entities.
8726  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8727  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8728  *         this array using decrRef() as it is no more needed.
8729  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8730  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8731  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8732  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8733  *         it is no more needed.  
8734  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8735  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8736  *         is no more needed.  
8737  *  \throw If the coordinates array is not set in any of the meshes.
8738  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8739  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8740  *
8741  *  \sa conformize2D, mergeNodes
8742  */
8743 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8744                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8745 {
8746   if(!m1 || !m2)
8747     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8748   m1->checkFullyDefined();
8749   m2->checkFullyDefined();
8750   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8751     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8752
8753   // Step 1: compute all edge intersections (new nodes)
8754   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8755   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8756   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8757   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8758   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8759                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8760                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8761   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8763   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8764
8765   // Step 2: re-order newly created nodes according to the ordering found in m2
8766   std::vector< std::vector<int> > intersectEdge2;
8767   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8768   subDiv2.clear(); dd5=0; dd6=0;
8769
8770   // Step 3:
8771   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8772   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8773   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8774                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8775
8776   // Step 4: Prepare final result:
8777   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8778   addCooDa->alloc((int)(addCoo.size())/2,2);
8779   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8780   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8781   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8782   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8783   std::vector<const DataArrayDouble *> coordss(4);
8784   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8785   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8786   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8788   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8789   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8790   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8791   ret->setConnectivity(conn,connI,true);
8792   ret->setCoords(coo);
8793   cellNb1=c1.retn(); cellNb2=c2.retn();
8794   return ret.retn();
8795 }
8796
8797 /// @cond INTERNAL
8798
8799 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8800 {
8801   if(candidates.empty())
8802     return false;
8803   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8804     {
8805       const std::vector<int>& pool(intersectEdge1[*it]);
8806       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8807       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8808         {
8809           retVal=*it+1;
8810           return true;
8811         }
8812       tmp[0]=stop; tmp[1]=start;
8813       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8814         {
8815           retVal=-*it-1;
8816           return true;
8817         }
8818     }
8819   return false;
8820 }
8821
8822 MEDCouplingUMesh *BuildMesh1DCutFrom(const MEDCouplingUMesh *mesh1D, const std::vector< std::vector<int> >& intersectEdge2, const DataArrayDouble *coords1, const std::vector<double>& addCoo, const std::map<int,int>& mergedNodes, const std::vector< std::vector<int> >& colinear2, const std::vector< std::vector<int> >& intersectEdge1,
8823                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8824 {
8825   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8826   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8827   int nCells(mesh1D->getNumberOfCells());
8828   if(nCells!=(int)intersectEdge2.size())
8829     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8830   const DataArrayDouble *coo2(mesh1D->getCoords());
8831   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8832   const double *coo2Ptr(coo2->begin());
8833   int offset1(coords1->getNumberOfTuples());
8834   int offset2(offset1+coo2->getNumberOfTuples());
8835   int offset3(offset2+addCoo.size()/2);
8836   std::vector<double> addCooQuad;
8837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8838   int tmp[4],cicnt(0),kk(0);
8839   for(int i=0;i<nCells;i++)
8840     {
8841       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8842       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8843       const std::vector<int>& subEdges(intersectEdge2[i]);
8844       int nbSubEdge(subEdges.size()/2);
8845       for(int j=0;j<nbSubEdge;j++,kk++)
8846         {
8847           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
8848           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8849           INTERP_KERNEL::Edge *e2Ptr(e2);
8850           std::map<int,int>::const_iterator itm;
8851           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8852             {
8853               tmp[0]=INTERP_KERNEL::NORM_SEG3;
8854               itm=mergedNodes.find(subEdges[2*j]);
8855               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8856               itm=mergedNodes.find(subEdges[2*j+1]);
8857               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8858               tmp[3]=offset3+(int)addCooQuad.size()/2;
8859               double tmp2[2];
8860               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8861               cicnt+=4;
8862               cOut->insertAtTheEnd(tmp,tmp+4);
8863               ciOut->pushBackSilent(cicnt);
8864             }
8865           else
8866             {
8867               tmp[0]=INTERP_KERNEL::NORM_SEG2;
8868               itm=mergedNodes.find(subEdges[2*j]);
8869               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8870               itm=mergedNodes.find(subEdges[2*j+1]);
8871               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8872               cicnt+=3;
8873               cOut->insertAtTheEnd(tmp,tmp+3);
8874               ciOut->pushBackSilent(cicnt);
8875             }
8876           int tmp00;
8877           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8878             {
8879               idsInRetColinear->pushBackSilent(kk);
8880               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8881             }
8882         }
8883       e->decrRef();
8884     }
8885   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8886   ret->setConnectivity(cOut,ciOut,true);
8887   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8888   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8889   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8890   std::vector<const DataArrayDouble *> coordss(4);
8891   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8892   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8893   ret->setCoords(arr);
8894   return ret.retn();
8895 }
8896
8897 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8898 {
8899   std::vector<int> allEdges;
8900   for(const int *it2(descBg);it2!=descEnd;it2++)
8901     {
8902       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8903       if(*it2>0)
8904         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8905       else
8906         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8907     }
8908   std::size_t nb(allEdges.size());
8909   if(nb%2!=0)
8910     throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !");
8911   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8912   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8913   ret->setCoords(coords);
8914   ret->allocateCells(1);
8915   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8916   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8917     connOut[kk]=allEdges[2*kk];
8918   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8919   return ret.retn();
8920 }
8921
8922 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
8923 {
8924   bool isQuad(false);
8925   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
8926     {
8927       const INTERP_KERNEL::Edge *ee(*it);
8928       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
8929         isQuad=true;
8930     }
8931   if(!isQuad)
8932     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
8933   else
8934     {
8935       const double *coo(mesh2D->getCoords()->begin());
8936       std::size_t sz(conn.size());
8937       std::vector<double> addCoo;
8938       std::vector<int> conn2(conn);
8939       int offset(mesh2D->getNumberOfNodes());
8940       for(std::size_t i=0;i<sz;i++)
8941         {
8942           double tmp[2];
8943           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);
8944           addCoo.insert(addCoo.end(),tmp,tmp+2);
8945           conn2.push_back(offset+(int)i);
8946         }
8947       mesh2D->getCoords()->rearrange(1);
8948       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
8949       mesh2D->getCoords()->rearrange(2);
8950       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
8951     }
8952 }
8953
8954 /*!
8955  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
8956  */
8957 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
8958                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
8959 {
8960   std::size_t nb(edge1Bis.size()/2);
8961   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8962   int iEnd(splitMesh1D->getNumberOfCells());
8963   if(iEnd==0)
8964     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
8965   std::size_t ii,jj;
8966   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
8967   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
8968   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
8969   //
8970   if(jj==nb)
8971     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
8972       out0.resize(1); out1.resize(1);
8973       std::vector<int>& connOut(out0[0]);
8974       connOut.resize(nbOfEdgesOf2DCellSplit);
8975       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
8976       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
8977       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8978         {
8979           connOut[kk]=edge1Bis[2*kk];
8980           edgesPtr[kk]=edge1BisPtr[2*kk];
8981         }
8982     }
8983   else
8984     {
8985       // [i,iEnd[ contains the
8986       out0.resize(2); out1.resize(2);
8987       std::vector<int>& connOutLeft(out0[0]);
8988       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
8989       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
8990       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
8991       for(std::size_t k=ii;k<jj+1;k++)
8992         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
8993       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
8994       for(int ik=iEnd-1;ik>=0;ik--)
8995         {
8996           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8997           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
8998           ees[iEnd-1-ik]=ee;
8999         }
9000       for(int ik=iEnd-1;ik>=0;ik--)
9001         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9002       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9003         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9004       eleft.insert(eleft.end(),ees.begin(),ees.end());
9005       for(int ik=0;ik<iEnd;ik++)
9006         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9007       eright.insert(eright.end(),ees.rbegin(),ees.rend());
9008     }
9009 }
9010
9011 /// @endcond
9012
9013 /// @cond INTERNAL
9014
9015 struct CellInfo
9016 {
9017 public:
9018   CellInfo() { }
9019   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9020 public:
9021   std::vector<int> _edges;
9022   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9023 };
9024
9025 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9026 {
9027   std::size_t nbe(edges.size());
9028   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9029   for(std::size_t i=0;i<nbe;i++)
9030     {
9031       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9032       edgesPtr2[2*i]=edgesPtr[i]; edgesPtr2[2*i+1]=edgesPtr[i];
9033     }
9034   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9035   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9036   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9037 }
9038
9039 class EdgeInfo
9040 {
9041 public:
9042   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9043   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9044   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9045   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9046   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9047 private:
9048   int _istart;
9049   int _iend;
9050   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9051   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9052   int _left;
9053   int _right;
9054 };
9055
9056 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9057 {
9058   const MEDCouplingUMesh *mesh(_mesh);
9059   if(mesh)
9060     return ;
9061   if(_right<pos)
9062     return ;
9063   if(_left>pos)
9064     { _left++; _right++; return ; }
9065   if(_right==pos)
9066     {
9067       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9068       if((isLeft && isRight) || (!isLeft && !isRight))
9069         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9070       if(isLeft)
9071         return ;
9072       if(isRight)
9073         {
9074           _right++;
9075           return ;
9076         }
9077     }
9078   if(_left==pos)
9079     {
9080       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9081       if((isLeft && isRight) || (!isLeft && !isRight))
9082         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9083       if(isLeft)
9084         {
9085           _right++;
9086           return ;
9087         }
9088       if(isRight)
9089         {
9090           _left++;
9091           _right++;
9092           return ;
9093         }
9094     }
9095 }
9096
9097 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9098 {
9099   const MEDCouplingUMesh *mesh(_mesh);
9100   if(!mesh)
9101     {
9102       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9103     }
9104   else
9105     {// not fully splitting cell case
9106       if(mesh2D->getNumberOfCells()==1)
9107         {//little optimization. 1 cell no need to find in which cell mesh is !
9108           neighbors[0]=offset; neighbors[1]=offset;
9109           return;
9110         }
9111       else
9112         {
9113           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9114           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9115           if(cellId==-1)
9116             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9117           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9118         }
9119     }
9120 }
9121
9122 class VectorOfCellInfo
9123 {
9124 public:
9125   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9126   std::size_t size() const { return _pool.size(); }
9127   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9128   void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9129   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9130   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9131   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9132   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9133 private:
9134   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9135   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9136   const CellInfo& get(int pos) const;
9137   CellInfo& get(int pos);
9138 private:
9139   std::vector<CellInfo> _pool;
9140   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9141   std::vector<EdgeInfo> _edge_info;
9142 };
9143
9144 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9145 {
9146   _pool[0]._edges=edges;
9147   _pool[0]._edges_ptr=edgesPtr;
9148 }
9149
9150 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9151 {
9152   if(_pool.empty())
9153     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9154   if(_pool.size()==1)
9155     return 0;
9156   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9157   if(!zeMesh)
9158     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9159   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9160   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9161 }
9162
9163 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9164 {
9165   get(pos);//to check pos
9166   bool isFast(pos==0 && _pool.size()==1);
9167   std::size_t sz(edges.size());
9168   // dealing with edges
9169   if(sz==1)
9170     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9171   else
9172     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9173   //
9174   std::vector<CellInfo> pool(_pool.size()-1+sz);
9175   for(int i=0;i<pos;i++)
9176     pool[i]=_pool[i];
9177   for(std::size_t j=0;j<sz;j++)
9178     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9179   for(int i=pos+1;i<(int)_pool.size();i++)
9180     pool[pos+sz-1]=_pool[i];
9181   _pool=pool;
9182   //
9183   if(sz==2)
9184     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9185   //
9186   if(isFast)
9187     {
9188       _ze_mesh=mesh;
9189       return ;
9190     }
9191   //
9192   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9193   if(pos>0)
9194     {
9195       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9196       ms.push_back(elt);
9197     }
9198   ms.push_back(mesh);
9199   if(pos<_ze_mesh->getNumberOfCells()-1)
9200   {
9201     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9202     ms.push_back(elt);
9203   }
9204   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9205   for(std::size_t j=0;j<ms2.size();j++)
9206     ms2[j]=ms[j];
9207   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9208 }
9209
9210 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9211 {
9212   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9213 }
9214
9215 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9216 {
9217   if(pos<0)
9218     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9219   int ret(0);
9220   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9221     {
9222       if((*it).isInMyRange(pos))
9223         return ret;
9224     }
9225   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9226 }
9227
9228 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9229 {
9230   get(pos);//to check;
9231   if(_edge_info.empty())
9232     return ;
9233   std::size_t sz(_edge_info.size()-1);
9234   for(std::size_t i=0;i<sz;i++)
9235     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9236 }
9237
9238 const CellInfo& VectorOfCellInfo::get(int pos) const
9239 {
9240   if(pos<0 || pos>=(int)_pool.size())
9241     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9242   return _pool[pos];
9243 }
9244
9245 CellInfo& VectorOfCellInfo::get(int pos)
9246 {
9247   if(pos<0 || pos>=(int)_pool.size())
9248     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9249   return _pool[pos];
9250 }
9251
9252 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9253                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9254 {
9255   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9256   if(nbCellsInSplitMesh1D==0)
9257     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9258   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9259   std::size_t nb(allEdges.size()),jj;
9260   if(nb%2!=0)
9261     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9262   std::vector<int> edge1Bis(nb*2);
9263   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9264   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9265   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9266   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9267   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9268   //
9269   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9270   int *idsLeftRightPtr(idsLeftRight->getPointer());
9271   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9272   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9273     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9274       int iEnd(iStart);
9275       for(;iEnd<nbCellsInSplitMesh1D;)
9276         {
9277           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9278           if(jj!=nb)
9279             break;
9280           else
9281             iEnd++;
9282         }
9283       if(iEnd<nbCellsInSplitMesh1D)
9284         iEnd++;
9285       //
9286       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9287       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9288       //
9289       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9290       retTmp->setCoords(splitMesh1D->getCoords());
9291       retTmp->allocateCells();
9292
9293       std::vector< std::vector<int> > out0;
9294       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9295
9296       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9297       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9298         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9299       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9300       //
9301       iStart=iEnd;
9302     }
9303   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9304     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9305   return pool.getZeMesh().retn();
9306 }
9307
9308 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9309                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9310                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9311 {
9312   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9313   //
9314   std::vector<int> allEdges;
9315   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr;
9316   for(const int *it(descBg);it!=descEnd;it++)
9317     {
9318       int edgeId(std::abs(*it)-1);
9319       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9320       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9321       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9322       if(*it>0)
9323         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9324       else
9325         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9326       std::size_t sz(edge1.size());
9327       for(std::size_t cnt=0;cnt<sz;cnt++)
9328         allEdgesPtr.push_back(ee);
9329     }
9330   //
9331   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9332 }
9333
9334 /// @endcond
9335
9336 /*!
9337  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9338  * Thus the final result contains the aggregation of nodes of \a mesh2D, then nodes of \a mesh1D, then new nodes that are the result of the intersection
9339  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9340  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9341  *
9342  * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool. The mesh must be so that each point in the space covered by \a mesh2D
9343  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9344  * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D. \a mesh1D must be ordered consecutively. If it is not the case
9345  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9346  * \param [in] eps - precision used to perform intersections and localization operations.
9347  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9348  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9349  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9350  *                               So this array has a number of tuples equal to the number of cells of \a splitMesh2D and a number of component equal to 1.
9351  * \param [out] cellIdInMesh1D - the array of pair that gives for each cell id \a i in \a splitMesh1D the cell in \a splitMesh2D on the left for the 1st component
9352  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9353  *                               So this array has a number of tuples equal to the number of cells of \a splitMesh1D and a number of components equal to 2.
9354  *
9355  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9356  */
9357 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9358 {
9359   if(!mesh2D || !mesh1D)
9360     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9361   mesh2D->checkFullyDefined();
9362   mesh1D->checkFullyDefined();
9363   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9364   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9365     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9366   // Step 1: compute all edge intersections (new nodes)
9367   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9368   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9369   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9370   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9371   //
9372   // Build desc connectivity
9373   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9375   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9376   std::map<int,int> mergedNodes;
9377   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9378   // use mergeNodes to fix intersectEdge1
9379   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9380     {
9381       std::size_t n((*it0).size()/2);
9382       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9383       std::map<int,int>::const_iterator it1;
9384       it1=mergedNodes.find(eltStart);
9385       if(it1!=mergedNodes.end())
9386         (*it0)[0]=(*it1).second;
9387       it1=mergedNodes.find(eltEnd);
9388       if(it1!=mergedNodes.end())
9389         (*it0)[2*n-1]=(*it1).second;
9390     }
9391   //
9392   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9393   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9394   // Step 2: re-order newly created nodes according to the ordering found in m2
9395   std::vector< std::vector<int> > intersectEdge2;
9396   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9397   subDiv2.clear();
9398   // Step 3: compute splitMesh1D
9399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9402       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2);
9404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9405   // deal with cells in mesh2D that are not cut but only some of their edges are
9406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9407   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9408   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9409   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9410   if(!idsInDesc2DToBeRefined->empty())
9411     {
9412       DataArrayInt *out0(0),*outi0(0);
9413       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9414       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9415       out0s=out0;
9416       out0s=out0s->buildUnique();
9417       out0s->sort(true);
9418     }
9419   //
9420   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9421   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9422   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9423   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9424   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9425   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9426   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9427     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9428   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9430   if((DataArrayInt *)out0s)
9431     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9432   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9433   // OK all is ready to insert in ret2 mesh
9434   if(!untouchedCells->empty())
9435     {// the most easy part, cells in mesh2D not impacted at all
9436       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9437       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9438       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9439     }
9440   if((DataArrayInt *)out0s)
9441     {// here dealing with cells in out0s but not in cellsToBeModified
9442       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9443       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9444       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9445         {
9446           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9447         }
9448       int offset(ret2->getNumberOfTuples());
9449       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9450       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9451       partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2);
9452       int kk(0),*ret3ptr(partOfRet3->getPointer());
9453       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9454         {
9455           int faceId(std::abs(*it)-1);
9456           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9457             {
9458               int tmp(fewModifiedCells->locateValue(*it2));
9459               if(tmp!=-1)
9460                 {
9461                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9462                     ret3ptr[2*kk]=tmp+offset;
9463                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9464                     ret3ptr[2*kk+1]=tmp+offset;
9465                 }
9466               else
9467                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !");
9468             }
9469         }
9470       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9471     }
9472   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9473     {
9474       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9475       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9476       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9477       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9478       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9479       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9480       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9481       outMesh2DSplit.push_back(splitOfOneCell);
9482       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9483         ret2->pushBackSilent(*it);
9484     }
9485   //
9486   std::size_t nbOfMeshes(outMesh2DSplit.size());
9487   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9488   for(std::size_t i=0;i<nbOfMeshes;i++)
9489     tmp[i]=outMesh2DSplit[i];
9490   //
9491   ret1->getCoords()->setInfoOnComponents(compNames);
9492   //
9493   splitMesh1D=ret1.retn();
9494   splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp);
9495   cellIdInMesh2D=ret2.retn();
9496   cellIdInMesh1D=ret3.retn();
9497 }
9498
9499 /**
9500  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9501  * (newly created) nodes corresponding to the edge intersections.
9502  * Output params:
9503  * @param[out] cr, crI connectivity of the resulting mesh
9504  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9505  * TODO: describe input parameters
9506  */
9507 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9508                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9509                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9510                                                          const std::vector<double>& addCoords,
9511                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9512 {
9513   static const int SPACEDIM=2;
9514   const double *coo1(m1->getCoords()->getConstPointer());
9515   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9516   int offset1(m1->getNumberOfNodes());
9517   const double *coo2(m2->getCoords()->getConstPointer());
9518   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9519   int offset2(offset1+m2->getNumberOfNodes());
9520   int offset3(offset2+((int)addCoords.size())/2);
9521   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9522   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9523   // Here a BBTree on 2D-cells, not on segments:
9524   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9525   int ncell1(m1->getNumberOfCells());
9526   crI.push_back(0);
9527   for(int i=0;i<ncell1;i++)
9528     {
9529       std::vector<int> candidates2;
9530       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9531       std::map<INTERP_KERNEL::Node *,int> mapp;
9532       std::map<int,INTERP_KERNEL::Node *> mappRev;
9533       INTERP_KERNEL::QuadraticPolygon pol1;
9534       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9535       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9536       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9537       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9538       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9539       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9540           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9541       //
9542       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
9543       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9544       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9545       for(it1.first();!it1.finished();it1.next())
9546         edges1.insert(it1.current()->getPtr());
9547       //
9548       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9549       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9550       int ii=0;
9551       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9552         {
9553           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9554           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9555           // Complete mapping with elements coming from the current cell it2 in mesh2:
9556           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9557           // pol2 is the new QP in the final merged result.
9558           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9559               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9560         }
9561       ii=0;
9562       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9563         {
9564           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9565           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9566           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9567           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9568         }
9569       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9570       // by m2 but that we still want to keep in the final result.
9571       if(!edges1.empty())
9572         {
9573           try
9574           {
9575               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9576           }
9577           catch(INTERP_KERNEL::Exception& e)
9578           {
9579               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();
9580               throw INTERP_KERNEL::Exception(oss.str().c_str());
9581           }
9582         }
9583       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9584         (*it).second->decrRef();
9585     }
9586 }
9587
9588 /**
9589  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9590  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9591  * This doesn't modify the mesh.
9592  * The caller is to deal with the resulting DataArrayInt.
9593  *  \throw If the coordinate array is not set.
9594  *  \throw If the nodal connectivity of the cells is not defined.
9595  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9596  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9597  */
9598 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9599 {
9600   checkFullyDefined();
9601   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
9602     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with (meshdim, spacedim) = (1,2)!");
9603
9604   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9605   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9606   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9607   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9608   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9609   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9610   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9611   const int * dsi(_dsi->getConstPointer());
9612   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9613   m_points=0;
9614   if (dsii->getNumberOfTuples())
9615     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9616
9617   int nc(getNumberOfCells());
9618   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9619   result->alloc(nc,1);
9620
9621   // set of edges not used so far
9622   std::set<int> edgeSet;
9623   for (int i=0; i<nc; edgeSet.insert(i), i++);
9624
9625   int startSeg=0;
9626   int newIdx=0;
9627   // while we have points with only one neighbor segments
9628   do
9629     {
9630       std::list<int> linePiece;
9631       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9632       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9633         {
9634           // Fill the list forward (resp. backward) from the start segment:
9635           int activeSeg = startSeg;
9636           int prevPointId = -20;
9637           int ptId;
9638           while (!edgeSet.empty())
9639             {
9640               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9641                 {
9642                   if (direction==0)
9643                     linePiece.push_back(activeSeg);
9644                   else
9645                     linePiece.push_front(activeSeg);
9646                   edgeSet.erase(activeSeg);
9647                 }
9648
9649               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9650               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9651               if (dsi[ptId] == 1) // hitting the end of the line
9652                 break;
9653               prevPointId = ptId;
9654               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9655               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9656             }
9657         }
9658       // Done, save final piece into DA:
9659       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9660       newIdx += linePiece.size();
9661
9662       // identify next valid start segment (one which is not consumed)
9663       if(!edgeSet.empty())
9664         startSeg = *(edgeSet.begin());
9665     }
9666   while (!edgeSet.empty());
9667   return result.retn();
9668 }
9669
9670 /// @cond INTERNAL
9671
9672 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9673 {
9674   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9675   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9676   if(it==m.end())
9677     throw INTERP_KERNEL::Exception("Internal error in remapping !");
9678   int v((*it).second);
9679   if(v==forbVal0 || v==forbVal1)
9680     return ;
9681   if(std::find(isect.begin(),isect.end(),v)==isect.end())
9682     isect.push_back(v);
9683 }
9684
9685 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9686 {
9687   int sz(c.size());
9688   if(sz<=1)
9689     return false;
9690   bool presenceOfOn(false);
9691   for(int i=0;i<sz;i++)
9692     {
9693       INTERP_KERNEL::ElementaryEdge *e(c[i]);
9694       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9695         continue ;
9696       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9697       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9698     }
9699   return presenceOfOn;
9700 }
9701
9702 /// @endcond
9703
9704 /**
9705  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
9706  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
9707  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
9708  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9709  *
9710  * \return int - the number of new nodes created (in most of cases 0).
9711  * 
9712  * \throw If \a this is not coherent.
9713  * \throw If \a this has not spaceDim equal to 2.
9714  * \throw If \a this has not meshDim equal to 2.
9715  * \throw If some subcells needed to be split are orphan.
9716  * \sa MEDCouplingUMesh::conformize2D
9717  */
9718 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9719 {
9720   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9721     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9722   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9723   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9724     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9725   if(midOpt==0 && midOptI==0)
9726     {
9727       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9728       return 0;
9729     }
9730   else if(midOpt!=0 && midOptI!=0)
9731     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9732   else
9733     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9734 }
9735
9736 /*!
9737  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9738  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9739  * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method
9740  * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges are both linear (INTERP_KERNEL::NORM_SEG2).
9741  * In the other cases new nodes can be created. If any are created, they will be appended at the end of the coordinates object before the invokation of this method.
9742  * 
9743  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9744  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9745  *
9746  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9747  * This method expects that all nodes in \a this are not closer than \a eps.
9748  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9749  * 
9750  * \param [in] eps the relative error to detect merged edges.
9751  * \return DataArrayInt  * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array
9752  *                           that the user is expected to deal with.
9753  *
9754  * \throw If \a this is not coherent.
9755  * \throw If \a this has not spaceDim equal to 2.
9756  * \throw If \a this has not meshDim equal to 2.
9757  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9758  */
9759 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9760 {
9761   static const int SPACEDIM=2;
9762   checkCoherency();
9763   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9764     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9765   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9766   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9767   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9768   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9769   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9770   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9771   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9772   std::vector<double> addCoo;
9773   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9774   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9775   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9776   for(int i=0;i<nDescCell;i++)
9777     {
9778       std::vector<int> candidates;
9779       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9780       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9781         if(*it>i)
9782           {
9783             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9784             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9785                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9786             INTERP_KERNEL::MergePoints merge;
9787             INTERP_KERNEL::QuadraticPolygon c1,c2;
9788             e1->intersectWith(e2,merge,c1,c2);
9789             e1->decrRef(); e2->decrRef();
9790             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9791               overlapEdge[i].push_back(*it);
9792             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9793               overlapEdge[*it].push_back(i);
9794           }
9795     }
9796   // splitting done. sort intersect point in intersectEdge.
9797   std::vector< std::vector<int> > middle(nDescCell);
9798   int nbOf2DCellsToBeSplit(0);
9799   bool middleNeedsToBeUsed(false);
9800   std::vector<bool> cells2DToTreat(nDescCell,false);
9801   for(int i=0;i<nDescCell;i++)
9802     {
9803       std::vector<int>& isect(intersectEdge[i]);
9804       int sz((int)isect.size());
9805       if(sz>1)
9806         {
9807           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9808           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9809           e->sortSubNodesAbs(coords,isect);
9810           e->decrRef();
9811         }
9812       if(sz!=0)
9813         {
9814           int idx0(rdi[i]),idx1(rdi[i+1]);
9815           if(idx1-idx0!=1)
9816             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9817           if(!cells2DToTreat[rd[idx0]])
9818             {
9819               cells2DToTreat[rd[idx0]]=true;
9820               nbOf2DCellsToBeSplit++;
9821             }
9822           // try to reuse at most eventual 'middle' of SEG3
9823           std::vector<int>& mid(middle[i]);
9824           mid.resize(sz+1,-1);
9825           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9826             {
9827               middleNeedsToBeUsed=true;
9828               const std::vector<int>& candidates(overlapEdge[i]);
9829               std::vector<int> trueCandidates;
9830               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9831                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9832                   trueCandidates.push_back(*itc);
9833               int stNode(c[ci[i]+1]),endNode(isect[0]);
9834               for(int j=0;j<sz+1;j++)
9835                 {
9836                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9837                     {
9838                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9839                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9840                         { mid[j]=*itc; break; }
9841                     }
9842                   stNode=endNode;
9843                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9844                 }
9845             }
9846         }
9847     }
9848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9849   if(nbOf2DCellsToBeSplit==0)
9850     return ret.retn();
9851   //
9852   int *retPtr(ret->getPointer());
9853   for(int i=0;i<nCell;i++)
9854     if(cells2DToTreat[i])
9855       *retPtr++=i;
9856   //
9857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9858   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9859   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9860   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9861   if(middleNeedsToBeUsed)
9862     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9863   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9864   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9865   setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important.
9866   setPartOfMySelf(ret->begin(),ret->end(),*modif);
9867   {
9868     bool areNodesMerged; int newNbOfNodes;
9869     if(nbOfNodesCreated!=0)
9870       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9871   }
9872   return ret.retn();
9873 }
9874
9875 /*!
9876  * This non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell.
9877  * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision).
9878  * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected
9879  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9880  * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells
9881  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9882  *
9883  * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified
9884  * using new instance, idem for coordinates.
9885  *
9886  * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this.
9887  * 
9888  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
9889  *
9890  * \throw If \a this is not coherent.
9891  * \throw If \a this has not spaceDim equal to 2.
9892  * \throw If \a this has not meshDim equal to 2.
9893  * 
9894  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9895  */
9896 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9897 {
9898   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9899   checkCoherency();
9900   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9902   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9903   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9904   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9905   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9907   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9908   const double *coords(_coords->begin());
9909   int *newciptr(newci->getPointer());
9910   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9911     {
9912       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9913         ret->pushBackSilent(i);
9914       newciptr[1]=newc->getNumberOfTuples();
9915     }
9916   //
9917   if(ret->empty())
9918     return ret.retn();
9919   if(!appendedCoords->empty())
9920     {
9921       appendedCoords->rearrange(2);
9922       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9923       //non const part
9924       setCoords(newCoords);
9925     }
9926   //non const part
9927   setConnectivity(newc,newci,true);
9928   return ret.retn();
9929 }
9930
9931 /*!
9932  * \param [out] intersectEdge1 - for each cell in \a m1Desc returns the result of the split. The result is given using pair of int given resp start and stop.
9933  *                               So for all edge \a i in \a m1Desc \a  intersectEdge1[i] is of length 2*n where n is the number of sub edges.
9934  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9935  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9936  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9937  * \param [out] addCoo - nodes to be append at the end
9938  * \param [out] mergedNodes - gives all pair of nodes of \a m2Desc that have same location than some nodes in \a m1Desc. key is id in \a m2Desc offseted and value is id in \a m1Desc.
9939  */
9940 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
9941                                          std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2, std::vector<double>& addCoo, std::map<int,int>& mergedNodes)
9942 {
9943   static const int SPACEDIM=2;
9944   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9945   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9946   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
9947   // Build BB tree of all edges in the tool mesh (second mesh)
9948   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9949   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9950   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
9951   intersectEdge1.resize(nDescCell1);
9952   colinear2.resize(nDescCell2);
9953   subDiv2.resize(nDescCell2);
9954   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9955
9956   std::vector<int> candidates1(1);
9957   int offset1(m1Desc->getNumberOfNodes());
9958   int offset2(offset1+m2Desc->getNumberOfNodes());
9959   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
9960     {
9961       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9962       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9963       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9964         {
9965           std::map<INTERP_KERNEL::Node *,int> map1,map2;
9966           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9967           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9968           candidates1[0]=i;
9969           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9970           // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
9971           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9972           std::set<INTERP_KERNEL::Node *> nodes;
9973           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9974           std::size_t szz(nodes.size());
9975           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9976           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9977           for(std::size_t iii=0;iii<szz;iii++,itt++)
9978             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9979           // end of protection
9980           // Performs egde cutting:
9981           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
9982           delete pol2;
9983           delete pol1;
9984         }
9985       else
9986         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9987     }
9988 }
9989
9990 /*!
9991  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
9992  * It builds the descending connectivity of the two meshes, and then using a binary tree
9993  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
9994  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
9995  */
9996 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
9997                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9998                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9999                                                    std::vector<double>& addCoo,
10000                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10001 {
10002   // Build desc connectivity
10003   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10004   desc2=DataArrayInt::New();
10005   descIndx2=DataArrayInt::New();
10006   revDesc2=DataArrayInt::New();
10007   revDescIndx2=DataArrayInt::New();
10008   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10009   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10010   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10011   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10012   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10013   std::map<int,int> notUsedMap;
10014   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10015   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10016   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10017 }
10018
10019 /*!
10020  * This method performs the 2nd step of Partition of 2D mesh.
10021  * This method has 4 inputs :
10022  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10023  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10024  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10025  * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
10026  * Nodes end up lying consecutively on a cutted edge.
10027  * \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.
10028  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10029  * \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.
10030  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10031  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10032  */
10033 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10034                                            const std::vector<double>& addCoo,
10035                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10036 {
10037   int offset1=m1->getNumberOfNodes();
10038   int ncell=m2->getNumberOfCells();
10039   const int *c=m2->getNodalConnectivity()->getConstPointer();
10040   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10041   const double *coo=m2->getCoords()->getConstPointer();
10042   const double *cooBis=m1->getCoords()->getConstPointer();
10043   int offset2=offset1+m2->getNumberOfNodes();
10044   intersectEdge.resize(ncell);
10045   for(int i=0;i<ncell;i++,cI++)
10046     {
10047       const std::vector<int>& divs=subDiv[i];
10048       int nnode=cI[1]-cI[0]-1;
10049       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10050       std::map<INTERP_KERNEL::Node *, int> mapp22;
10051       for(int j=0;j<nnode;j++)
10052         {
10053           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10054           int nnid=c[(*cI)+j+1];
10055           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10056           mapp22[nn]=nnid+offset1;
10057         }
10058       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10059       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10060         ((*it).second.first)->decrRef();
10061       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10062       std::map<INTERP_KERNEL::Node *,int> mapp3;
10063       for(std::size_t j=0;j<divs.size();j++)
10064         {
10065           int id=divs[j];
10066           INTERP_KERNEL::Node *tmp=0;
10067           if(id<offset1)
10068             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10069           else if(id<offset2)
10070             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10071           else
10072             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10073           addNodes[j]=tmp;
10074           mapp3[tmp]=id;
10075         }
10076       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10077       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10078         (*it)->decrRef();
10079       e->decrRef();
10080     }
10081 }
10082
10083 /*!
10084  * 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).
10085  * 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
10086  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10087  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10088  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10089  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10090  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10091  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10092  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10093  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10094  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10095  * \param [out] cut3DSuf input/output param.
10096  */
10097 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10098                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10099                                                    const int *desc, const int *descIndx, 
10100                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10101 {
10102   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10103   int nbOf3DSurfCell=(int)cut3DSurf.size();
10104   for(int i=0;i<nbOf3DSurfCell;i++)
10105     {
10106       std::vector<int> res;
10107       int offset=descIndx[i];
10108       int nbOfSeg=descIndx[i+1]-offset;
10109       for(int j=0;j<nbOfSeg;j++)
10110         {
10111           int edgeId=desc[offset+j];
10112           int status=cut3DCurve[edgeId];
10113           if(status!=-2)
10114             {
10115               if(status>-1)
10116                 res.push_back(status);
10117               else
10118                 {
10119                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10120                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10121                 }
10122             }
10123         }
10124       switch(res.size())
10125       {
10126         case 2:
10127           {
10128             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10129             break;
10130           }
10131         case 1:
10132         case 0:
10133           {
10134             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10135             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10136             if(res.size()==2)
10137               {
10138                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10139               }
10140             else
10141               {
10142                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10143               }
10144             break;
10145           }
10146         default:
10147           {// case when plane is on a multi colinear edge of a polyhedron
10148             if((int)res.size()==2*nbOfSeg)
10149               {
10150                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10151               }
10152             else
10153               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10154           }
10155       }
10156     }
10157 }
10158
10159 /*!
10160  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10161  * 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).
10162  * 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
10163  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10164  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10165  * \param desc is the descending connectivity 3D->3DSurf
10166  * \param descIndx is the descending connectivity index 3D->3DSurf
10167  */
10168 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10169                                                   const int *desc, const int *descIndx,
10170                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10171 {
10172   checkFullyDefined();
10173   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10175   const int *nodal3D=_nodal_connec->getConstPointer();
10176   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10177   int nbOfCells=getNumberOfCells();
10178   for(int i=0;i<nbOfCells;i++)
10179     {
10180       std::map<int, std::set<int> > m;
10181       int offset=descIndx[i];
10182       int nbOfFaces=descIndx[i+1]-offset;
10183       int start=-1;
10184       int end=-1;
10185       for(int j=0;j<nbOfFaces;j++)
10186         {
10187           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10188           if(p.first!=-1 && p.second!=-1)
10189             {
10190               if(p.first!=-2)
10191                 {
10192                   start=p.first; end=p.second;
10193                   m[p.first].insert(p.second);
10194                   m[p.second].insert(p.first);
10195                 }
10196               else
10197                 {
10198                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10199                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10200                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10201                   INTERP_KERNEL::NormalizedCellType cmsId;
10202                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10203                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10204                   for(unsigned k=0;k<nbOfNodesSon;k++)
10205                     {
10206                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10207                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10208                     }
10209                 }
10210             }
10211         }
10212       if(m.empty())
10213         continue;
10214       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10215       int prev=end;
10216       while(end!=start)
10217         {
10218           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10219           const std::set<int>& s=(*it).second;
10220           std::set<int> s2; s2.insert(prev);
10221           std::set<int> s3;
10222           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10223           if(s3.size()==1)
10224             {
10225               int val=*s3.begin();
10226               conn.push_back(start);
10227               prev=start;
10228               start=val;
10229             }
10230           else
10231             start=end;
10232         }
10233       conn.push_back(end);
10234       if(conn.size()>3)
10235         {
10236           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10237           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10238           cellIds->pushBackSilent(i);
10239         }
10240     }
10241 }
10242
10243 /*!
10244  * 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
10245  * 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
10246  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10247  * 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
10248  * 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.
10249  * 
10250  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10251  */
10252 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10253 {
10254   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10255   if(sz>=4)
10256     {
10257       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10258       if(cm.getDimension()==2)
10259         {
10260           const int *node=nodalConnBg+1;
10261           int startNode=*node++;
10262           double refX=coords[2*startNode];
10263           for(;node!=nodalConnEnd;node++)
10264             {
10265               if(coords[2*(*node)]<refX)
10266                 {
10267                   startNode=*node;
10268                   refX=coords[2*startNode];
10269                 }
10270             }
10271           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10272           refX=1e300;
10273           double tmp1;
10274           double tmp2[2];
10275           double angle0=-M_PI/2;
10276           //
10277           int nextNode=-1;
10278           int prevNode=-1;
10279           double resRef;
10280           double angleNext=0.;
10281           while(nextNode!=startNode)
10282             {
10283               nextNode=-1;
10284               resRef=1e300;
10285               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10286                 {
10287                   if(*node!=tmpOut.back() && *node!=prevNode)
10288                     {
10289                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10290                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10291                       double res;
10292                       if(angleM<=angle0)
10293                         res=angle0-angleM;
10294                       else
10295                         res=angle0-angleM+2.*M_PI;
10296                       if(res<resRef)
10297                         {
10298                           nextNode=*node;
10299                           resRef=res;
10300                           angleNext=angleM;
10301                         }
10302                     }
10303                 }
10304               if(nextNode!=startNode)
10305                 {
10306                   angle0=angleNext-M_PI;
10307                   if(angle0<-M_PI)
10308                     angle0+=2*M_PI;
10309                   prevNode=tmpOut.back();
10310                   tmpOut.push_back(nextNode);
10311                 }
10312             }
10313           std::vector<int> tmp3(2*(sz-1));
10314           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10315           std::copy(nodalConnBg+1,nodalConnEnd,it);
10316           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10317             {
10318               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10319               return false;
10320             }
10321           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10322             {
10323               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10324               return false;
10325             }
10326           else
10327             {
10328               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10329               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10330               return true;
10331             }
10332         }
10333       else
10334         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10335     }
10336   else
10337     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10338 }
10339
10340 /*!
10341  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10342  * 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.
10343  * 
10344  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10345  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10346  * \param [in,out] arr array in which the remove operation will be done.
10347  * \param [in,out] arrIndx array in the remove operation will modify
10348  * \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])
10349  * \return true if \b arr and \b arrIndx have been modified, false if not.
10350  */
10351 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10352 {
10353   if(!arrIndx || !arr)
10354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10355   if(offsetForRemoval<0)
10356     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10357   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10358   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10359   int *arrIPtr=arrIndx->getPointer();
10360   *arrIPtr++=0;
10361   int previousArrI=0;
10362   const int *arrPtr=arr->getConstPointer();
10363   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10364   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10365     {
10366       if(*arrIPtr-previousArrI>offsetForRemoval)
10367         {
10368           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10369             {
10370               if(s.find(*work)==s.end())
10371                 arrOut.push_back(*work);
10372             }
10373         }
10374       previousArrI=*arrIPtr;
10375       *arrIPtr=(int)arrOut.size();
10376     }
10377   if(arr->getNumberOfTuples()==(int)arrOut.size())
10378     return false;
10379   arr->alloc((int)arrOut.size(),1);
10380   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10381   return true;
10382 }
10383
10384 /*!
10385  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10386  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10387  * The selection of extraction is done standardly in new2old format.
10388  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10389  *
10390  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10391  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10392  * \param [in] arrIn arr origin array from which the extraction will be done.
10393  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10394  * \param [out] arrOut the resulting array
10395  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10396  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10397  */
10398 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10399                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10400 {
10401   if(!arrIn || !arrIndxIn)
10402     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10403   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10404   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10405     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10406   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10407   const int *arrInPtr=arrIn->getConstPointer();
10408   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10409   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10410   if(nbOfGrps<0)
10411     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10412   int maxSizeOfArr=arrIn->getNumberOfTuples();
10413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10414   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10415   arrIo->alloc((int)(sz+1),1);
10416   const int *idsIt=idsOfSelectBg;
10417   int *work=arrIo->getPointer();
10418   *work++=0;
10419   int lgth=0;
10420   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10421     {
10422       if(*idsIt>=0 && *idsIt<nbOfGrps)
10423         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10424       else
10425         {
10426           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10427           throw INTERP_KERNEL::Exception(oss.str().c_str());
10428         }
10429       if(lgth>=work[-1])
10430         *work=lgth;
10431       else
10432         {
10433           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10434           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10435           throw INTERP_KERNEL::Exception(oss.str().c_str());
10436         }
10437     }
10438   arro->alloc(lgth,1);
10439   work=arro->getPointer();
10440   idsIt=idsOfSelectBg;
10441   for(std::size_t i=0;i<sz;i++,idsIt++)
10442     {
10443       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10444         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10445       else
10446         {
10447           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10448           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10449           throw INTERP_KERNEL::Exception(oss.str().c_str());
10450         }
10451     }
10452   arrOut=arro.retn();
10453   arrIndexOut=arrIo.retn();
10454 }
10455
10456 /*!
10457  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10458  * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
10459  * The selection of extraction is done standardly in new2old format.
10460  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10461  *
10462  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10463  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10464  * \param [in] arrIn arr origin array from which the extraction will be done.
10465  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10466  * \param [out] arrOut the resulting array
10467  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10468  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10469  */
10470 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10471                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10472 {
10473   if(!arrIn || !arrIndxIn)
10474     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10475   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10476   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10477     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10478   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10479   const int *arrInPtr=arrIn->getConstPointer();
10480   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10481   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10482   if(nbOfGrps<0)
10483     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10484   int maxSizeOfArr=arrIn->getNumberOfTuples();
10485   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10486   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10487   arrIo->alloc((int)(sz+1),1);
10488   int idsIt=idsOfSelectStart;
10489   int *work=arrIo->getPointer();
10490   *work++=0;
10491   int lgth=0;
10492   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10493     {
10494       if(idsIt>=0 && idsIt<nbOfGrps)
10495         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10496       else
10497         {
10498           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10499           throw INTERP_KERNEL::Exception(oss.str().c_str());
10500         }
10501       if(lgth>=work[-1])
10502         *work=lgth;
10503       else
10504         {
10505           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10506           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10507           throw INTERP_KERNEL::Exception(oss.str().c_str());
10508         }
10509     }
10510   arro->alloc(lgth,1);
10511   work=arro->getPointer();
10512   idsIt=idsOfSelectStart;
10513   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10514     {
10515       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10516         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10517       else
10518         {
10519           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10520           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10521           throw INTERP_KERNEL::Exception(oss.str().c_str());
10522         }
10523     }
10524   arrOut=arro.retn();
10525   arrIndexOut=arrIo.retn();
10526 }
10527
10528 /*!
10529  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10530  * 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
10531  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10532  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10533  *
10534  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10535  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10536  * \param [in] arrIn arr origin array from which the extraction will be done.
10537  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10538  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10539  * \param [in] srcArrIndex index array of \b srcArr
10540  * \param [out] arrOut the resulting array
10541  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10542  * 
10543  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10544  */
10545 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10546                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10547                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10548 {
10549   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10550     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10551   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10552   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10553   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10554   std::vector<bool> v(nbOfTuples,true);
10555   int offset=0;
10556   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10557   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10558   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10559     {
10560       if(*it>=0 && *it<nbOfTuples)
10561         {
10562           v[*it]=false;
10563           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10564         }
10565       else
10566         {
10567           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10568           throw INTERP_KERNEL::Exception(oss.str().c_str());
10569         }
10570     }
10571   srcArrIndexPtr=srcArrIndex->getConstPointer();
10572   arrIo->alloc(nbOfTuples+1,1);
10573   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10574   const int *arrInPtr=arrIn->getConstPointer();
10575   const int *srcArrPtr=srcArr->getConstPointer();
10576   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10577   int *arroPtr=arro->getPointer();
10578   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10579     {
10580       if(v[ii])
10581         {
10582           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10583           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10584         }
10585       else
10586         {
10587           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10588           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10589           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10590         }
10591     }
10592   arrOut=arro.retn();
10593   arrIndexOut=arrIo.retn();
10594 }
10595
10596 /*!
10597  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10598  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10599  *
10600  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10601  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10602  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10603  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10604  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10605  * \param [in] srcArrIndex index array of \b srcArr
10606  * 
10607  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10608  */
10609 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10610                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10611 {
10612   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10613     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10614   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10615   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10616   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10617   int *arrInOutPtr=arrInOut->getPointer();
10618   const int *srcArrPtr=srcArr->getConstPointer();
10619   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10620     {
10621       if(*it>=0 && *it<nbOfTuples)
10622         {
10623           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10624             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10625           else
10626             {
10627               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] !";
10628               throw INTERP_KERNEL::Exception(oss.str().c_str());
10629             }
10630         }
10631       else
10632         {
10633           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10634           throw INTERP_KERNEL::Exception(oss.str().c_str());
10635         }
10636     }
10637 }
10638
10639 /*!
10640  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10641  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10642  * 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]].
10643  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10644  * A negative value in \b arrIn means that it is ignored.
10645  * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
10646  * 
10647  * \param [in] arrIn arr origin array from which the extraction will be done.
10648  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10649  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10650  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10651  */
10652 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10653 {
10654   int seed=0,nbOfDepthPeelingPerformed=0;
10655   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10656 }
10657
10658 /*!
10659  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10660  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10661  * 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]].
10662  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10663  * A negative value in \b arrIn means that it is ignored.
10664  * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
10665  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10666  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10667  * \param [in] arrIn arr origin array from which the extraction will be done.
10668  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10669  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10670  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10671  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10672  * \sa MEDCouplingUMesh::partitionBySpreadZone
10673  */
10674 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10675 {
10676   nbOfDepthPeelingPerformed=0;
10677   if(!arrIndxIn)
10678     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10679   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10680   if(nbOfTuples<=0)
10681     {
10682       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10683       return ret;
10684     }
10685   //
10686   std::vector<bool> fetched(nbOfTuples,false);
10687   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10688 }
10689
10690 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10691 {
10692   nbOfDepthPeelingPerformed=0;
10693   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10695   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10696   std::vector<bool> fetched2(nbOfTuples,false);
10697   int i=0;
10698   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10699     {
10700       if(*seedElt>=0 && *seedElt<nbOfTuples)
10701         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10702       else
10703         { 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()); }
10704     }
10705   const int *arrInPtr=arrIn->getConstPointer();
10706   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10707   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10708   std::vector<int> idsToFetch1(seedBg,seedEnd);
10709   std::vector<int> idsToFetch2;
10710   std::vector<int> *idsToFetch=&idsToFetch1;
10711   std::vector<int> *idsToFetchOther=&idsToFetch2;
10712   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10713     {
10714       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10715         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10716           if(!fetched[*it2])
10717             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10718       std::swap(idsToFetch,idsToFetchOther);
10719       idsToFetchOther->clear();
10720       nbOfDepthPeelingPerformed++;
10721     }
10722   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10723   i=0;
10724   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10725   int *retPtr=ret->getPointer();
10726   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10727     if(*it)
10728       *retPtr++=i;
10729   return ret.retn();
10730 }
10731
10732 /*!
10733  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10734  * 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
10735  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10736  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10737  *
10738  * \param [in] start begin of set of ids of the input extraction (included)
10739  * \param [in] end end of set of ids of the input extraction (excluded)
10740  * \param [in] step step of the set of ids in range mode.
10741  * \param [in] arrIn arr origin array from which the extraction will be done.
10742  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10743  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10744  * \param [in] srcArrIndex index array of \b srcArr
10745  * \param [out] arrOut the resulting array
10746  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10747  * 
10748  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10749  */
10750 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10751                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10752                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10753 {
10754   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10755     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10758   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10759   int offset=0;
10760   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10761   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10762   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10763   int it=start;
10764   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10765     {
10766       if(it>=0 && it<nbOfTuples)
10767         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10768       else
10769         {
10770           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10771           throw INTERP_KERNEL::Exception(oss.str().c_str());
10772         }
10773     }
10774   srcArrIndexPtr=srcArrIndex->getConstPointer();
10775   arrIo->alloc(nbOfTuples+1,1);
10776   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10777   const int *arrInPtr=arrIn->getConstPointer();
10778   const int *srcArrPtr=srcArr->getConstPointer();
10779   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10780   int *arroPtr=arro->getPointer();
10781   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10782     {
10783       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10784       if(pos<0)
10785         {
10786           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10787           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10788         }
10789       else
10790         {
10791           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10792           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10793         }
10794     }
10795   arrOut=arro.retn();
10796   arrIndexOut=arrIo.retn();
10797 }
10798
10799 /*!
10800  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10801  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10802  *
10803  * \param [in] start begin of set of ids of the input extraction (included)
10804  * \param [in] end end of set of ids of the input extraction (excluded)
10805  * \param [in] step step of the set of ids in range mode.
10806  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10807  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10808  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10809  * \param [in] srcArrIndex index array of \b srcArr
10810  * 
10811  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10812  */
10813 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10814                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10815 {
10816   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10817     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10818   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10819   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10820   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10821   int *arrInOutPtr=arrInOut->getPointer();
10822   const int *srcArrPtr=srcArr->getConstPointer();
10823   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10824   int it=start;
10825   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10826     {
10827       if(it>=0 && it<nbOfTuples)
10828         {
10829           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10830             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10831           else
10832             {
10833               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10834               throw INTERP_KERNEL::Exception(oss.str().c_str());
10835             }
10836         }
10837       else
10838         {
10839           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10840           throw INTERP_KERNEL::Exception(oss.str().c_str());
10841         }
10842     }
10843 }
10844
10845 /*!
10846  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10847  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10848  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10849  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10850  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10851  * 
10852  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10853  */
10854 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10855 {
10856   checkFullyDefined();
10857   int mdim=getMeshDimension();
10858   int spaceDim=getSpaceDimension();
10859   if(mdim!=spaceDim)
10860     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10861   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10862   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10863   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10864   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10865   ret->setCoords(getCoords());
10866   ret->allocateCells((int)partition.size());
10867   //
10868   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10869     {
10870       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10871       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10872       switch(mdim)
10873       {
10874         case 2:
10875           cell=tmp->buildUnionOf2DMesh();
10876           break;
10877         case 3:
10878           cell=tmp->buildUnionOf3DMesh();
10879           break;
10880         default:
10881           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10882       }
10883
10884       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10885     }
10886   //
10887   ret->finishInsertingCells();
10888   return ret.retn();
10889 }
10890
10891 /*!
10892  * This method partitions \b this into contiguous zone.
10893  * This method only needs a well defined connectivity. Coordinates are not considered here.
10894  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10895  */
10896 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10897 {
10898   int nbOfCellsCur=getNumberOfCells();
10899   std::vector<DataArrayInt *> ret;
10900   if(nbOfCellsCur<=0)
10901     return ret;
10902   DataArrayInt *neigh=0,*neighI=0;
10903   computeNeighborsOfCells(neigh,neighI);
10904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10905   std::vector<bool> fetchedCells(nbOfCellsCur,false);
10906   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10907   int seed=0;
10908   while(seed<nbOfCellsCur)
10909     {
10910       int nbOfPeelPerformed=0;
10911       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10912       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10913     }
10914   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10915     ret.push_back((*it).retn());
10916   return ret;
10917 }
10918
10919 /*!
10920  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10921  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10922  *
10923  * \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.
10924  * \return a newly allocated DataArrayInt to be managed by the caller.
10925  * \throw In case of \a code has not the right format (typically of size 3*n)
10926  */
10927 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10928 {
10929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10930   std::size_t nb=code.size()/3;
10931   if(code.size()%3!=0)
10932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10933   ret->alloc((int)nb,2);
10934   int *retPtr=ret->getPointer();
10935   for(std::size_t i=0;i<nb;i++,retPtr+=2)
10936     {
10937       retPtr[0]=code[3*i+2];
10938       retPtr[1]=code[3*i+2]+code[3*i+1];
10939     }
10940   return ret.retn();
10941 }
10942
10943 /*!
10944  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10945  * All cells in \a this are expected to be linear 3D cells.
10946  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10947  * It leads to an increase to number of cells.
10948  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10949  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
10950  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10951  *
10952  * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
10953  *                      For all other cells, the splitting policy will be ignored.
10954  * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added. 
10955  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10956  *          an id of old cell producing it. The caller is to delete this array using
10957  *         decrRef() as it is no more needed.
10958  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10959  *
10960  * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
10961  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10962  * 
10963  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10964  * \throw If \a this is not fully constituted with linear 3D cells.
10965  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10966  */
10967 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10968 {
10969   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10970   checkConnectivityFullyDefined();
10971   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10973   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10974   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10976   int *retPt(ret->getPointer());
10977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10978   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10979   const int *oldc(_nodal_connec->begin());
10980   const int *oldci(_nodal_connec_index->begin());
10981   const double *coords(_coords->begin());
10982   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10983     {
10984       std::vector<int> a; std::vector<double> b;
10985       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10986       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10987       const int *aa(&a[0]);
10988       if(!b.empty())
10989         {
10990           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10991             if(*it<0)
10992               *it=(-(*(it))-1+nbNodes);
10993           addPts->insertAtTheEnd(b.begin(),b.end());
10994           nbNodes+=(int)b.size()/3;
10995         }
10996       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10997         newConn->insertAtTheEnd(aa,aa+4);
10998     }
10999   if(!addPts->empty())
11000     {
11001       addPts->rearrange(3);
11002       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11003       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11004       ret0->setCoords(addPts);
11005     }
11006   else
11007     {
11008       nbOfAdditionalPoints=0;
11009       ret0->setCoords(getCoords());
11010     }
11011   ret0->setNodalConnectivity(newConn);
11012   //
11013   ret->computeOffsets2();
11014   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11015   return ret0.retn();
11016 }
11017
11018 /*!
11019  * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch). 
11020  *
11021  * \sa MEDCouplingUMesh::split2DCells
11022  */
11023 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11024 {
11025   checkConnectivityFullyDefined();
11026   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11027   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11028   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11029   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11030   int prevPosOfCi(ciPtr[0]);
11031   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11032     {
11033       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11034       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11035       for(int j=0;j<sz;j++)
11036         {
11037           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11038           for(int k=0;k<sz2;k++)
11039             *cPtr++=subPtr[offset2+k];
11040           if(j!=sz-1)
11041             *cPtr++=oldConn[prevPosOfCi+j+2];
11042           deltaSz+=sz2;
11043         }
11044       prevPosOfCi=ciPtr[1];
11045       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11046     }
11047   if(c->end()!=cPtr)
11048     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11049   _nodal_connec->decrRef();
11050   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11051 }
11052
11053 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11054 {
11055   if(id!=-1)
11056     return id;
11057   else
11058     {
11059       int ret(nodesCnter++);
11060       double newPt[2];
11061       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11062       addCoo.insertAtTheEnd(newPt,newPt+2);
11063       return ret;
11064     }
11065 }
11066
11067 /// @cond INTERNAL
11068
11069 void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11070 {
11071   int tmp[3];
11072   int trueStart(start>=0?start:nbOfEdges+start);
11073   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11074   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11075   if(linOrArc)
11076     {
11077       if(stp-start>1)
11078         {
11079           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11080           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11081           middles.push_back(tmp3+offset);
11082         }
11083       else
11084         middles.push_back(connBg[trueStart+nbOfEdges]);
11085     }
11086 }
11087
11088 void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11089 {
11090   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11091   newConnOfCell->pushBackSilent(tmpEnd);
11092   if(linOrArc)
11093     {
11094       if(stp-start>1)
11095         {
11096           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11097           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11098           middles.push_back(tmp3+offset);
11099         }
11100       else
11101         middles.push_back(connBg[start+nbOfEdges]);
11102     }
11103 }
11104
11105 void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11106 {
11107   if(linOrArc)
11108     {
11109       if(stp-start>1)
11110         {
11111           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11112           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11113           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11114           middles.push_back(tmp3+offset);
11115         }
11116       else
11117         middles.push_back(connBg[start+nbOfEdges]);
11118     }
11119 }
11120
11121 /// @cond INTERNAL
11122
11123 /*!
11124  * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) .
11125  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11126  */
11127 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11128 {
11129   std::size_t sz(std::distance(connBg,connEnd));
11130   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11131     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11132   sz--;
11133   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11134   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11135   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11136   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11137   INTERP_KERNEL::NormalizedCellType typeOfSon;
11138   std::vector<int> middles;
11139   bool ret(false);
11140   for(;nbOfHit<nbs;nbOfTurn++)
11141     {
11142       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11143       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11144       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11145       posEndElt++;
11146       nbOfHit++;
11147       unsigned endI(nbs-nbOfHit);
11148       for(unsigned i=0;i<endI;i++)
11149         {
11150           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11151           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11152           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11153           bool isColinear(eint->areColinears());
11154           if(isColinear)
11155             {
11156               nbOfHit++;
11157               posEndElt++;
11158               ret=true;
11159             }
11160           delete eint;
11161           eCand->decrRef();
11162           if(!isColinear)
11163             {
11164               if(nbOfTurn==0)
11165                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11166                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11167                   for(unsigned ii=0;ii<endII;ii++)
11168                     {
11169                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11170                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11171                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11172                       isColinear=eint->areColinears();
11173                       if(isColinear)
11174                         {
11175                           nbOfHit++;
11176                           posBaseElt--;
11177                           ret=true;
11178                         }
11179                       delete eint;
11180                       eCand->decrRef();
11181                       if(!isColinear)
11182                         break;
11183                     }
11184                 }
11185               break;
11186             }
11187         }
11188       //push [posBaseElt,posEndElt) in newConnOfCell using e
11189       if(nbOfTurn==0)
11190         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11191       else if(nbOfHit!=nbs)
11192         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11193       else
11194         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11195       posBaseElt=posEndElt;
11196       e->decrRef();
11197     }
11198   if(!middles.empty())
11199     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11200   return ret;
11201 }
11202
11203 /*!
11204  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11205  *
11206  * \return  int - the number of new nodes created.
11207  * \sa MEDCouplingUMesh::split2DCells
11208  */
11209 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11210 {
11211   checkCoherency();
11212   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11214   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11215   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11216   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11217   const double *oldCoordsPtr(getCoords()->begin());
11218   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11219   int prevPosOfCi(ciPtr[0]);
11220   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11221     {
11222       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11223       for(int j=0;j<sz;j++)
11224         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11225       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11226       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11227         {
11228           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11229           if(sz2==0)
11230             {
11231               if(j<sz-1)
11232                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11233               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11234               continue;
11235             }
11236           std::vector<INTERP_KERNEL::Node *> ns(3);
11237           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11238           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11239           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11240           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11241           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11242             {
11243               cPtr[1]=subPtr[offset2+k];
11244               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11245             }
11246           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11247           if(j!=sz-1)
11248             { cPtr[1]=tmpEnd; }
11249           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11250         }
11251       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11252       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11253     }
11254   if(c->end()!=cPtr)
11255     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11256   _nodal_connec->decrRef();
11257   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11258   addCoo->rearrange(2);
11259   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11260   setCoords(coo);
11261   return addCoo->getNumberOfTuples();
11262 }
11263
11264 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11265     _own_cell(true),_cell_id(-1),_nb_cell(0)
11266 {
11267   if(mesh)
11268     {
11269       mesh->incrRef();
11270       _nb_cell=mesh->getNumberOfCells();
11271     }
11272 }
11273
11274 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11275 {
11276   if(_mesh)
11277     _mesh->decrRef();
11278   if(_own_cell)
11279     delete _cell;
11280 }
11281
11282 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11283     _own_cell(false),_cell_id(bg-1),
11284     _nb_cell(end)
11285 {
11286   if(mesh)
11287     mesh->incrRef();
11288 }
11289
11290 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11291 {
11292   _cell_id++;
11293   if(_cell_id<_nb_cell)
11294     {
11295       _cell->next();
11296       return _cell;
11297     }
11298   else
11299     return 0;
11300 }
11301
11302 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11303 {
11304   if(_mesh)
11305     _mesh->incrRef();
11306 }
11307
11308 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11309 {
11310   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11311 }
11312
11313 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11314 {
11315   if(_mesh)
11316     _mesh->decrRef();
11317 }
11318
11319 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11320     _itc(itc),
11321     _bg(bg),_end(end)
11322 {
11323   if(_mesh)
11324     _mesh->incrRef();
11325 }
11326
11327 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11328 {
11329   if(_mesh)
11330     _mesh->decrRef();
11331 }
11332
11333 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11334 {
11335   return _type;
11336 }
11337
11338 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11339 {
11340   return _end-_bg;
11341 }
11342
11343 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11344 {
11345   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11346 }
11347
11348 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11349 {
11350   if(mesh)
11351     {
11352       mesh->incrRef();
11353       _nb_cell=mesh->getNumberOfCells();
11354     }
11355 }
11356
11357 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11358 {
11359   if(_mesh)
11360     _mesh->decrRef();
11361   delete _cell;
11362 }
11363
11364 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11365 {
11366   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11367   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11368   if(_cell_id<_nb_cell)
11369     {
11370       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11371       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11372       int startId=_cell_id;
11373       _cell_id+=nbOfElems;
11374       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11375     }
11376   else
11377     return 0;
11378 }
11379
11380 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11381 {
11382   if(mesh)
11383     {
11384       _conn=mesh->getNodalConnectivity()->getPointer();
11385       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11386     }
11387 }
11388
11389 void MEDCouplingUMeshCell::next()
11390 {
11391   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11392     {
11393       _conn+=_conn_lgth;
11394       _conn_indx++;
11395     }
11396   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11397 }
11398
11399 std::string MEDCouplingUMeshCell::repr() const
11400 {
11401   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11402     {
11403       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11404       oss << " : ";
11405       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11406       return oss.str();
11407     }
11408   else
11409     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11410 }
11411
11412 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11413 {
11414   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11415     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11416   else
11417     return INTERP_KERNEL::NORM_ERROR;
11418 }
11419
11420 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11421 {
11422   lgth=_conn_lgth;
11423   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11424     return _conn;
11425   else
11426     return 0;
11427 }