Salome HOME
Dealing with quadratic polygons. Ready to integrate Adrien tests.
[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::getDirectChildren() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
128   if(_nodal_connec)
129     ret.push_back(_nodal_connec);
130   if(_nodal_connec_index)
131     ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
247         {
248           int nodeId=*w;
249           if(nodeId>=0)
250             {
251               if(nodeId>=nbOfNodes)
252                 {
253                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254                   throw INTERP_KERNEL::Exception(oss.str().c_str());
255                 }
256             }
257           else if(nodeId<-1)
258             {
259               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260               throw INTERP_KERNEL::Exception(oss.str().c_str());
261             }
262           else
263             {
264               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265                 {
266                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267                   throw INTERP_KERNEL::Exception(oss.str().c_str());
268                 }
269             }
270         }
271     }
272 }
273
274
275 /*!
276  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277  * then \a this mesh is most probably is writable, exchangeable and available for all
278  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
279  *  \param [in] eps - a not used parameter.
280  *  \throw If the mesh dimension is not set.
281  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
282  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283  *  \throw If the connectivity data array has more than one component.
284  *  \throw If the connectivity data array has a named component.
285  *  \throw If the connectivity index data array has more than one component.
286  *  \throw If the connectivity index data array has a named component.
287  *  \throw If number of nodes defining an element does not correspond to the type of element.
288  *  \throw If the nodal connectivity includes an invalid node id.
289  */
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
291 {
292   checkCoherency1(eps);
293 }
294
295 /*!
296  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297  * elements contained in the mesh. For more info on the mesh dimension see
298  * \ref MEDCouplingUMeshPage.
299  *  \param [in] meshDim - a new mesh dimension.
300  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301  */
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 {
304   if(meshDim<-1 || meshDim>3)
305     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
306   _mesh_dim=meshDim;
307   declareAsNew();
308 }
309
310 /*!
311  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314  *
315  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316  *
317  *  \if ENABLE_EXAMPLES
318  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
319  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
320  *  \endif
321  */
322 void MEDCouplingUMesh::allocateCells(int nbOfCells)
323 {
324   if(nbOfCells<0)
325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
326   if(_nodal_connec_index)
327     {
328       _nodal_connec_index->decrRef();
329     }
330   if(_nodal_connec)
331     {
332       _nodal_connec->decrRef();
333     }
334   _nodal_connec_index=DataArrayInt::New();
335   _nodal_connec_index->reserve(nbOfCells+1);
336   _nodal_connec_index->pushBackSilent(0);
337   _nodal_connec=DataArrayInt::New();
338   _nodal_connec->reserve(2*nbOfCells);
339   _types.clear();
340   declareAsNew();
341 }
342
343 /*!
344  * Appends a cell to the connectivity array. For deeper understanding what is
345  * happening see \ref MEDCouplingUMeshNodalConnectivity.
346  *  \param [in] type - type of cell to add.
347  *  \param [in] size - number of nodes constituting this cell.
348  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
349  * 
350  *  \if ENABLE_EXAMPLES
351  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
352  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
353  *  \endif
354  */
355 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
356 {
357   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
358   if(_nodal_connec_index==0)
359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
360   if((int)cm.getDimension()==_mesh_dim)
361     {
362       if(!cm.isDynamic())
363         if(size!=(int)cm.getNumberOfNodes())
364           {
365             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
366             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
367             throw INTERP_KERNEL::Exception(oss.str().c_str());
368           }
369       int idx=_nodal_connec_index->back();
370       int val=idx+size+1;
371       _nodal_connec_index->pushBackSilent(val);
372       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
373       _types.insert(type);
374     }
375   else
376     {
377       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
378       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
379       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
380       throw INTERP_KERNEL::Exception(oss.str().c_str());
381     }
382 }
383
384 /*!
385  * Compacts data arrays to release unused memory. This method is to be called after
386  * finishing cell insertion using \a this->insertNextCell().
387  * 
388  *  \if ENABLE_EXAMPLES
389  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
390  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
391  *  \endif
392  */
393 void MEDCouplingUMesh::finishInsertingCells()
394 {
395   _nodal_connec->pack();
396   _nodal_connec_index->pack();
397   _nodal_connec->declareAsNew();
398   _nodal_connec_index->declareAsNew();
399   updateTime();
400 }
401
402 /*!
403  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
404  * Useful for python users.
405  */
406 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
407 {
408   return new MEDCouplingUMeshCellIterator(this);
409 }
410
411 /*!
412  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
413  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
414  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
415  * Useful for python users.
416  */
417 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
418 {
419   if(!checkConsecutiveCellTypes())
420     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
421   return new MEDCouplingUMeshCellByTypeEntry(this);
422 }
423
424 /*!
425  * Returns a set of all cell types available in \a this mesh.
426  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
427  * \warning this method does not throw any exception even if \a this is not defined.
428  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
429  */
430 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
431 {
432   return _types;
433 }
434
435 /*!
436  * This method returns the sorted list of geometric types in \a this.
437  * 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
438  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
439  *
440  * \throw if connectivity in \a this is not correctly defined.
441  *  
442  * \sa MEDCouplingMesh::getAllGeoTypes
443  */
444 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
445 {
446   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
447   checkConnectivityFullyDefined();
448   int nbOfCells(getNumberOfCells());
449   if(nbOfCells==0)
450     return ret;
451   if(getMeshLength()<1)
452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
453   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
454   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
455   for(int i=1;i<nbOfCells;i++,ci++)
456     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
457       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
458   return ret;
459 }
460
461 /*!
462  * This method is a method that compares \a this and \a other.
463  * This method compares \b all attributes, even names and component names.
464  */
465 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
466 {
467   if(!other)
468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
469   std::ostringstream oss; oss.precision(15);
470   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
471   if(!otherC)
472     {
473       reason="mesh given in input is not castable in MEDCouplingUMesh !";
474       return false;
475     }
476   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
477     return false;
478   if(_mesh_dim!=otherC->_mesh_dim)
479     {
480       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
481       reason=oss.str();
482       return false;
483     }
484   if(_types!=otherC->_types)
485     {
486       oss << "umesh geometric type mismatch :\nThis geometric types are :";
487       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
488         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
489       oss << "\nOther geometric types are :";
490       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
491         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
492       reason=oss.str();
493       return false;
494     }
495   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
496     if(_nodal_connec==0 || otherC->_nodal_connec==0)
497       {
498         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
499         return false;
500       }
501   if(_nodal_connec!=otherC->_nodal_connec)
502     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
503       {
504         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
505         return false;
506       }
507   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
508     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
509       {
510         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
511         return false;
512       }
513   if(_nodal_connec_index!=otherC->_nodal_connec_index)
514     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
515       {
516         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
517         return false;
518       }
519   return true;
520 }
521
522 /*!
523  * Checks if data arrays of this mesh (node coordinates, nodal
524  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
525  * not considered.
526  *  \param [in] other - the mesh to compare with.
527  *  \param [in] prec - precision value used to compare node coordinates.
528  *  \return bool - \a true if the two meshes are same.
529  */
530 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
531 {
532   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
533   if(!otherC)
534     return false;
535   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
536     return false;
537   if(_mesh_dim!=otherC->_mesh_dim)
538     return false;
539   if(_types!=otherC->_types)
540     return false;
541   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
542     if(_nodal_connec==0 || otherC->_nodal_connec==0)
543       return false;
544   if(_nodal_connec!=otherC->_nodal_connec)
545     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
546       return false;
547   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
548     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
549       return false;
550   if(_nodal_connec_index!=otherC->_nodal_connec_index)
551     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
552       return false;
553   return true;
554 }
555
556 /*!
557  * Checks if \a this and \a other meshes are geometrically equivalent with high
558  * probability, else an exception is thrown. The meshes are considered equivalent if
559  * (1) meshes contain the same number of nodes and the same number of elements of the
560  * same types (2) three cells of the two meshes (first, last and middle) are based
561  * on coincident nodes (with a specified precision).
562  *  \param [in] other - the mesh to compare with.
563  *  \param [in] prec - the precision used to compare nodes of the two meshes.
564  *  \throw If the two meshes do not match.
565  */
566 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
567 {
568   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
569   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
570   if(!otherC)
571     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
572 }
573
574 /*!
575  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
576  * cells each node belongs to.
577  * \warning For speed reasons, this method does not check if node ids in the nodal
578  *          connectivity correspond to the size of node coordinates array.
579  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
580  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
581  *        dividing cell ids in \a revNodal into groups each referring to one
582  *        node. Its every element (except the last one) is an index pointing to the
583  *         first id of a group of cells. For example cells sharing the node #1 are 
584  *        described by following range of indices: 
585  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
586  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
587  *        Number of cells sharing the *i*-th node is
588  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
589  * \throw If the coordinates array is not set.
590  * \throw If the nodal connectivity of cells is not defined.
591  * 
592  * \if ENABLE_EXAMPLES
593  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
594  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
595  * \endif
596  */
597 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
598 {
599   checkFullyDefined();
600   int nbOfNodes=getNumberOfNodes();
601   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
602   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
603   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
604   const int *conn=_nodal_connec->getConstPointer();
605   const int *connIndex=_nodal_connec_index->getConstPointer();
606   int nbOfCells=getNumberOfCells();
607   int nbOfEltsInRevNodal=0;
608   for(int eltId=0;eltId<nbOfCells;eltId++)
609     {
610       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
611       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
612       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
613         if(*iter>=0)//for polyhedrons
614           {
615             nbOfEltsInRevNodal++;
616             revNodalIndxPtr[(*iter)+1]++;
617           }
618     }
619   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
620   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
621   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
622   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
623   for(int eltId=0;eltId<nbOfCells;eltId++)
624     {
625       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
626       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
627       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
628         if(*iter>=0)//for polyhedrons
629           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
630     }
631 }
632
633 /// @cond INTERNAL
634
635 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
636 {
637   return id;
638 }
639
640 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
641 {
642   if(!compute)
643     return id+1;
644   else
645     {
646       if(cm.getOrientationStatus(nb,conn1,conn2))
647         return id+1;
648       else
649         return -(id+1);
650     }
651 }
652
653 class MinusOneSonsGenerator
654 {
655 public:
656   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
657   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
658   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
659   static const int DELTA=1;
660 private:
661   const INTERP_KERNEL::CellModel& _cm;
662 };
663
664 class MinusOneSonsGeneratorBiQuadratic
665 {
666 public:
667   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670   static const int DELTA=1;
671 private:
672   const INTERP_KERNEL::CellModel& _cm;
673 };
674
675 class MinusTwoSonsGenerator
676 {
677 public:
678   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
680   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681   static const int DELTA=2;
682 private:
683   const INTERP_KERNEL::CellModel& _cm;
684 };
685
686 /// @endcond
687
688 /*!
689  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
690  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
691  * describing correspondence between cells of \a this and the result meshes are
692  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
693  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
694  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
695  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
696  * \warning For speed reasons, this method does not check if node ids in the nodal
697  *          connectivity correspond to the size of node coordinates array.
698  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
699  *          to write this mesh to the MED file, its cells must be sorted using
700  *          sortCellsInMEDFileFrmt().
701  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
702  *         each cell of \a this mesh.
703  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
704  *        dividing cell ids in \a desc into groups each referring to one
705  *        cell of \a this mesh. Its every element (except the last one) is an index
706  *        pointing to the first id of a group of cells. For example cells of the
707  *        result mesh bounding the cell #1 of \a this mesh are described by following
708  *        range of indices:
709  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
710  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
711  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
712  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
713  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
714  *         by each cell of the result mesh.
715  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
716  *        in the result mesh,
717  *        dividing cell ids in \a revDesc into groups each referring to one
718  *        cell of the result mesh the same way as \a descIndx divides \a desc.
719  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
720  *        delete this mesh using decrRef() as it is no more needed.
721  *  \throw If the coordinates array is not set.
722  *  \throw If the nodal connectivity of cells is node defined.
723  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
724  *         revDescIndx == NULL.
725  * 
726  *  \if ENABLE_EXAMPLES
727  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
728  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
729  *  \endif
730  * \sa buildDescendingConnectivity2()
731  */
732 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
733 {
734   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
735 }
736
737 /*!
738  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
739  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
740  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
741  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
742  * \sa MEDCouplingUMesh::buildDescendingConnectivity
743  */
744 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 {
746   checkFullyDefined();
747   if(getMeshDimension()!=3)
748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
749   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
750 }
751
752 /*!
753  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
754  * this->getMeshDimension(), that bound cells of \a this mesh. In
755  * addition arrays describing correspondence between cells of \a this and the result
756  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
757  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
758  *  mesh. This method differs from buildDescendingConnectivity() in that apart
759  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
760  * result meshes. So a positive id means that order of nodes in corresponding cells
761  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
762  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
763  * i.e. cell ids are one-based.
764  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
765  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
766  * \warning For speed reasons, this method does not check if node ids in the nodal
767  *          connectivity correspond to the size of node coordinates array.
768  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
769  *          to write this mesh to the MED file, its cells must be sorted using
770  *          sortCellsInMEDFileFrmt().
771  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
772  *         each cell of \a this mesh.
773  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
774  *        dividing cell ids in \a desc into groups each referring to one
775  *        cell of \a this mesh. Its every element (except the last one) is an index
776  *        pointing to the first id of a group of cells. For example cells of the
777  *        result mesh bounding the cell #1 of \a this mesh are described by following
778  *        range of indices:
779  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
780  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
781  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
782  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
783  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
784  *         by each cell of the result mesh.
785  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
786  *        in the result mesh,
787  *        dividing cell ids in \a revDesc into groups each referring to one
788  *        cell of the result mesh the same way as \a descIndx divides \a desc.
789  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
790  *        shares the node coordinates array with \a this mesh. The caller is to
791  *        delete this mesh using decrRef() as it is no more needed.
792  *  \throw If the coordinates array is not set.
793  *  \throw If the nodal connectivity of cells is node defined.
794  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
795  *         revDescIndx == NULL.
796  * 
797  *  \if ENABLE_EXAMPLES
798  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
799  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
800  *  \endif
801  * \sa buildDescendingConnectivity()
802  */
803 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
804 {
805   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
806 }
807
808 /*!
809  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
810  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
811  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
812  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
813  *
814  * \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
815  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
816  * \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.
817  */
818 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
819 {
820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
824   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
825   meshDM1=0;
826   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
827 }
828
829 /*!
830  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
831  * 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,
832  * excluding a set of meshdim-1 cells in input descending connectivity.
833  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
834  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
835  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
836  *
837  * \param [in] desc descending connectivity array.
838  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
839  * \param [in] revDesc reverse descending connectivity array.
840  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
841  * \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
842  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843  * \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.
844  */
845 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
846                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
847 {
848   if(!desc || !descIndx || !revDesc || !revDescIndx)
849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
850   const int *descPtr=desc->getConstPointer();
851   const int *descIPtr=descIndx->getConstPointer();
852   const int *revDescPtr=revDesc->getConstPointer();
853   const int *revDescIPtr=revDescIndx->getConstPointer();
854   //
855   int nbCells=descIndx->getNumberOfTuples()-1;
856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
858   int *out1Ptr=out1->getPointer();
859   *out1Ptr++=0;
860   out0->reserve(desc->getNumberOfTuples());
861   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
862     {
863       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
864         {
865           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
866           s.erase(i);
867           out0->insertAtTheEnd(s.begin(),s.end());
868         }
869       *out1Ptr=out0->getNumberOfTuples();
870     }
871   neighbors=out0.retn();
872   neighborsIndx=out1.retn();
873 }
874
875 /*!
876  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
877  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
878  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
879  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
880  *
881  * \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
882  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
883  * \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.
884  */
885 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
886 {
887   checkFullyDefined();
888   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
889   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
890   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
891   switch(mdim)
892   {
893     case 3:
894       {
895         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
896         break;
897       }
898     case 2:
899       {
900         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
901         break;
902       }
903     case 1:
904       {
905         mesh1D=const_cast<MEDCouplingUMesh *>(this);
906         mesh1D->incrRef();
907         break;
908       }
909     default:
910       {
911         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
912       }
913   }
914   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
915   mesh1D->getReverseNodalConnectivity(desc,descIndx);
916   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
917   ret0->alloc(desc->getNumberOfTuples(),1);
918   int *r0Pt(ret0->getPointer());
919   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
920   for(int i=0;i<nbNodes;i++,rni++)
921     {
922       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
923         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
924     }
925   neighbors=ret0.retn();
926   neighborsIdx=descIndx.retn();
927 }
928
929 /// @cond INTERNAL
930
931 /*!
932  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
933  * For speed reasons no check of this will be done.
934  */
935 template<class SonsGenerator>
936 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
937 {
938   if(!desc || !descIndx || !revDesc || !revDescIndx)
939     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
940   checkConnectivityFullyDefined();
941   int nbOfCells=getNumberOfCells();
942   int nbOfNodes=getNumberOfNodes();
943   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
944   int *revNodalIndxPtr=revNodalIndx->getPointer();
945   const int *conn=_nodal_connec->getConstPointer();
946   const int *connIndex=_nodal_connec_index->getConstPointer();
947   std::string name="Mesh constituent of "; name+=getName();
948   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
949   ret->setCoords(getCoords());
950   ret->allocateCells(2*nbOfCells);
951   descIndx->alloc(nbOfCells+1,1);
952   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
953   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
954   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
955     {
956       int pos=connIndex[eltId];
957       int posP1=connIndex[eltId+1];
958       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
959       SonsGenerator sg(cm);
960       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
961       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
962       for(unsigned i=0;i<nbOfSons;i++)
963         {
964           INTERP_KERNEL::NormalizedCellType cmsId;
965           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
966           for(unsigned k=0;k<nbOfNodesSon;k++)
967             if(tmp[k]>=0)
968               revNodalIndxPtr[tmp[k]+1]++;
969           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
970           revDesc2->pushBackSilent(eltId);
971         }
972       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
973     }
974   int nbOfCellsM1=ret->getNumberOfCells();
975   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
976   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
977   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
978   int *revNodalPtr=revNodal->getPointer();
979   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
980   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
981   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
982     {
983       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
984       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
985       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
986         if(*iter>=0)//for polyhedrons
987           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
988     }
989   //
990   DataArrayInt *commonCells=0,*commonCellsI=0;
991   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
992   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
993   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
994   int newNbOfCellsM1=-1;
995   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
996                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
997   std::vector<bool> isImpacted(nbOfCellsM1,false);
998   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
999     for(int work2=work[0];work2!=work[1];work2++)
1000       isImpacted[commonCellsPtr[work2]]=true;
1001   const int *o2nM1Ptr=o2nM1->getConstPointer();
1002   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1003   const int *n2oM1Ptr=n2oM1->getConstPointer();
1004   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1005   ret2->copyTinyInfoFrom(this);
1006   desc->alloc(descIndx->back(),1);
1007   int *descPtr=desc->getPointer();
1008   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1009   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1010     {
1011       if(!isImpacted[i])
1012         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1013       else
1014         {
1015           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1016             {
1017               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1018               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1019             }
1020           else
1021             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1022         }
1023     }
1024   revDesc->reserve(newNbOfCellsM1);
1025   revDescIndx->alloc(newNbOfCellsM1+1,1);
1026   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1027   const int *revDesc2Ptr=revDesc2->getConstPointer();
1028   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1029     {
1030       int oldCellIdM1=n2oM1Ptr[i];
1031       if(!isImpacted[oldCellIdM1])
1032         {
1033           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1034           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1035         }
1036       else
1037         {
1038           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1039             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1040           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1041           commonCellsIPtr++;
1042         }
1043     }
1044   //
1045   return ret2.retn();
1046 }
1047
1048 struct MEDCouplingAccVisit
1049 {
1050   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1051   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1052   int _new_nb_of_nodes;
1053 };
1054
1055 /// @endcond
1056
1057 /*!
1058  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1059  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1060  * array of cell ids. Pay attention that after conversion all algorithms work slower
1061  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1062  * conversion due presence of invalid ids in the array of cells to convert, as a
1063  * result \a this mesh contains some already converted elements. In this case the 2D
1064  * mesh remains valid but 3D mesh becomes \b inconsistent!
1065  *  \warning This method can significantly modify the order of geometric types in \a this,
1066  *          hence, to write this mesh to the MED file, its cells must be sorted using
1067  *          sortCellsInMEDFileFrmt().
1068  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1069  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1070  *         cellIdsToConvertBg.
1071  *  \throw If the coordinates array is not set.
1072  *  \throw If the nodal connectivity of cells is node defined.
1073  *  \throw If dimension of \a this mesh is not either 2 or 3.
1074  *
1075  *  \if ENABLE_EXAMPLES
1076  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1077  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1078  *  \endif
1079  */
1080 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1081 {
1082   checkFullyDefined();
1083   int dim=getMeshDimension();
1084   if(dim<2 || dim>3)
1085     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1086   int nbOfCells(getNumberOfCells());
1087   if(dim==2)
1088     {
1089       const int *connIndex=_nodal_connec_index->getConstPointer();
1090       int *conn=_nodal_connec->getPointer();
1091       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1092         {
1093           if(*iter>=0 && *iter<nbOfCells)
1094             {
1095               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1096               if(!cm.isQuadratic())
1097                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1098               else
1099                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1100             }
1101           else
1102             {
1103               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1104               oss << " in range [0," << nbOfCells << ") !";
1105               throw INTERP_KERNEL::Exception(oss.str().c_str());
1106             }
1107         }
1108     }
1109   else
1110     {
1111       int *connIndex(_nodal_connec_index->getPointer());
1112       const int *connOld(_nodal_connec->getConstPointer());
1113       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1114       std::vector<bool> toBeDone(nbOfCells,false);
1115       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1116         {
1117           if(*iter>=0 && *iter<nbOfCells)
1118             toBeDone[*iter]=true;
1119           else
1120             {
1121               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1122               oss << " in range [0," << nbOfCells << ") !";
1123               throw INTERP_KERNEL::Exception(oss.str().c_str());
1124             }
1125         }
1126       for(int cellId=0;cellId<nbOfCells;cellId++)
1127         {
1128           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1129           int lgthOld(posP1-pos-1);
1130           if(toBeDone[cellId])
1131             {
1132               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1133               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1134               int *tmp(new int[nbOfFaces*lgthOld+1]);
1135               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1136               for(unsigned j=0;j<nbOfFaces;j++)
1137                 {
1138                   INTERP_KERNEL::NormalizedCellType type;
1139                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1140                   work+=offset;
1141                   *work++=-1;
1142                 }
1143               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1144               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1145               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1146               delete [] tmp;
1147             }
1148           else
1149             {
1150               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1151               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1152             }
1153         }
1154       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1155     }
1156   computeTypes();
1157 }
1158
1159 /*!
1160  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1161  * polyhedrons (if \a this is a 3D mesh).
1162  *  \warning As this method is purely for user-friendliness and no optimization is
1163  *          done to avoid construction of a useless vector, this method can be costly
1164  *          in memory.
1165  *  \throw If the coordinates array is not set.
1166  *  \throw If the nodal connectivity of cells is node defined.
1167  *  \throw If dimension of \a this mesh is not either 2 or 3.
1168  */
1169 void MEDCouplingUMesh::convertAllToPoly()
1170 {
1171   int nbOfCells=getNumberOfCells();
1172   std::vector<int> cellIds(nbOfCells);
1173   for(int i=0;i<nbOfCells;i++)
1174     cellIds[i]=i;
1175   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1176 }
1177
1178 /*!
1179  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1180  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1181  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1182  * base facet of the volume and the second half of nodes describes an opposite facet
1183  * having the same number of nodes as the base one. This method converts such
1184  * connectivity to a valid polyhedral format where connectivity of each facet is
1185  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1186  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1187  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1188  * a correct orientation of the first facet of a polyhedron, else orientation of a
1189  * corrected cell is reverse.<br>
1190  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1191  * it releases the user from boring description of polyhedra connectivity in the valid
1192  * format.
1193  *  \throw If \a this->getMeshDimension() != 3.
1194  *  \throw If \a this->getSpaceDimension() != 3.
1195  *  \throw If the nodal connectivity of cells is not defined.
1196  *  \throw If the coordinates array is not set.
1197  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1198  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1199  *
1200  *  \if ENABLE_EXAMPLES
1201  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1202  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1203  *  \endif
1204  */
1205 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1206 {
1207   checkFullyDefined();
1208   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1210   int nbOfCells=getNumberOfCells();
1211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1212   newCi->alloc(nbOfCells+1,1);
1213   int *newci=newCi->getPointer();
1214   const int *ci=_nodal_connec_index->getConstPointer();
1215   const int *c=_nodal_connec->getConstPointer();
1216   newci[0]=0;
1217   for(int i=0;i<nbOfCells;i++)
1218     {
1219       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1220       if(type==INTERP_KERNEL::NORM_POLYHED)
1221         {
1222           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1223             {
1224               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1225               throw INTERP_KERNEL::Exception(oss.str().c_str());
1226             }
1227           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1228           if(n2%2!=0)
1229             {
1230               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 !";
1231               throw INTERP_KERNEL::Exception(oss.str().c_str());
1232             }
1233           int n1=(int)(n2/2);
1234           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)
1235         }
1236       else
1237         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1238     }
1239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1240   newC->alloc(newci[nbOfCells],1);
1241   int *newc=newC->getPointer();
1242   for(int i=0;i<nbOfCells;i++)
1243     {
1244       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1245       if(type==INTERP_KERNEL::NORM_POLYHED)
1246         {
1247           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1248           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1249           *newc++=-1;
1250           for(std::size_t j=0;j<n1;j++)
1251             {
1252               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1253               newc[n1+5*j]=-1;
1254               newc[n1+5*j+1]=c[ci[i]+1+j];
1255               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1256               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1257               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1258             }
1259           newc+=n1*6;
1260         }
1261       else
1262         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1263     }
1264   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1265   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1266 }
1267
1268
1269 /*!
1270  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1271  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1272  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1273  *          to write this mesh to the MED file, its cells must be sorted using
1274  *          sortCellsInMEDFileFrmt().
1275  * \return \c true if at least one cell has been converted, \c false else. In the
1276  *         last case the nodal connectivity remains unchanged.
1277  * \throw If the coordinates array is not set.
1278  * \throw If the nodal connectivity of cells is not defined.
1279  * \throw If \a this->getMeshDimension() < 0.
1280  */
1281 bool MEDCouplingUMesh::unPolyze()
1282 {
1283   checkFullyDefined();
1284   int mdim=getMeshDimension();
1285   if(mdim<0)
1286     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1287   if(mdim<=1)
1288     return false;
1289   int nbOfCells=getNumberOfCells();
1290   if(nbOfCells<1)
1291     return false;
1292   int initMeshLgth=getMeshLength();
1293   int *conn=_nodal_connec->getPointer();
1294   int *index=_nodal_connec_index->getPointer();
1295   int posOfCurCell=0;
1296   int newPos=0;
1297   int lgthOfCurCell;
1298   bool ret=false;
1299   for(int i=0;i<nbOfCells;i++)
1300     {
1301       lgthOfCurCell=index[i+1]-posOfCurCell;
1302       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1303       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1304       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1305       int newLgth;
1306       if(cm.isDynamic())
1307         {
1308           switch(cm.getDimension())
1309           {
1310             case 2:
1311               {
1312                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1313                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1314                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1315                 break;
1316               }
1317             case 3:
1318               {
1319                 int nbOfFaces,lgthOfPolyhConn;
1320                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1321                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1322                 break;
1323               }
1324             case 1:
1325               {
1326                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1327                 break;
1328               }
1329           }
1330           ret=ret || (newType!=type);
1331           conn[newPos]=newType;
1332           newPos+=newLgth+1;
1333           posOfCurCell=index[i+1];
1334           index[i+1]=newPos;
1335         }
1336       else
1337         {
1338           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1339           newPos+=lgthOfCurCell;
1340           posOfCurCell+=lgthOfCurCell;
1341           index[i+1]=newPos;
1342         }
1343     }
1344   if(newPos!=initMeshLgth)
1345     _nodal_connec->reAlloc(newPos);
1346   if(ret)
1347     computeTypes();
1348   return ret;
1349 }
1350
1351 /*!
1352  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1353  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1354  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1355  *
1356  * \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 
1357  *             precision.
1358  */
1359 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1360 {
1361   checkFullyDefined();
1362   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1363     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1364   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1365   coords->recenterForMaxPrecision(eps);
1366   //
1367   int nbOfCells=getNumberOfCells();
1368   const int *conn=_nodal_connec->getConstPointer();
1369   const int *index=_nodal_connec_index->getConstPointer();
1370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1371   connINew->alloc(nbOfCells+1,1);
1372   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1374   bool changed=false;
1375   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1376     {
1377       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1378         {
1379           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1380           changed=true;
1381         }
1382       else
1383         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1384       *connINewPtr=connNew->getNumberOfTuples();
1385     }
1386   if(changed)
1387     setConnectivity(connNew,connINew,false);
1388 }
1389
1390 /*!
1391  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1392  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1393  * the format of returned DataArrayInt instance.
1394  * 
1395  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1396  * \sa MEDCouplingUMesh::getNodeIdsInUse
1397  */
1398 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1399 {
1400   checkConnectivityFullyDefined();
1401   int nbOfCells=getNumberOfCells();
1402   const int *connIndex=_nodal_connec_index->getConstPointer();
1403   const int *conn=_nodal_connec->getConstPointer();
1404   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1405   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1406   std::vector<bool> retS(maxElt,false);
1407   for(int i=0;i<nbOfCells;i++)
1408     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1409       if(conn[j]>=0)
1410         retS[conn[j]]=true;
1411   int sz=0;
1412   for(int i=0;i<maxElt;i++)
1413     if(retS[i])
1414       sz++;
1415   DataArrayInt *ret=DataArrayInt::New();
1416   ret->alloc(sz,1);
1417   int *retPtr=ret->getPointer();
1418   for(int i=0;i<maxElt;i++)
1419     if(retS[i])
1420       *retPtr++=i;
1421   return ret;
1422 }
1423
1424 /*!
1425  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1426  * \sa MEDCouplingUMesh::getNodeIdsInUse
1427  */
1428 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1429 {
1430   int nbOfNodes=(int)nodeIdsInUse.size();
1431   int nbOfCells=getNumberOfCells();
1432   const int *connIndex=_nodal_connec_index->getConstPointer();
1433   const int *conn=_nodal_connec->getConstPointer();
1434   for(int i=0;i<nbOfCells;i++)
1435     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1436       if(conn[j]>=0)
1437         {
1438           if(conn[j]<nbOfNodes)
1439             nodeIdsInUse[conn[j]]=true;
1440           else
1441             {
1442               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1443               throw INTERP_KERNEL::Exception(oss.str().c_str());
1444             }
1445         }
1446 }
1447
1448 /*!
1449  * Finds nodes not used in any cell and returns an array giving a new id to every node
1450  * by excluding the unused nodes, for which the array holds -1. The result array is
1451  * a mapping in "Old to New" mode. 
1452  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1453  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1454  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1455  *          if the node is unused or a new id else. The caller is to delete this
1456  *          array using decrRef() as it is no more needed.  
1457  *  \throw If the coordinates array is not set.
1458  *  \throw If the nodal connectivity of cells is not defined.
1459  *  \throw If the nodal connectivity includes an invalid id.
1460  *
1461  *  \if ENABLE_EXAMPLES
1462  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1463  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1464  *  \endif
1465  * \sa computeNodeIdsAlg()
1466  */
1467 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1468 {
1469   nbrOfNodesInUse=-1;
1470   int nbOfNodes=getNumberOfNodes();
1471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1472   ret->alloc(nbOfNodes,1);
1473   int *traducer=ret->getPointer();
1474   std::fill(traducer,traducer+nbOfNodes,-1);
1475   int nbOfCells=getNumberOfCells();
1476   const int *connIndex=_nodal_connec_index->getConstPointer();
1477   const int *conn=_nodal_connec->getConstPointer();
1478   for(int i=0;i<nbOfCells;i++)
1479     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1480       if(conn[j]>=0)
1481         {
1482           if(conn[j]<nbOfNodes)
1483             traducer[conn[j]]=1;
1484           else
1485             {
1486               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1487               throw INTERP_KERNEL::Exception(oss.str().c_str());
1488             }
1489         }
1490   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1491   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1492   return ret.retn();
1493 }
1494
1495 /*!
1496  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1497  * For each cell in \b this the number of nodes constituting cell is computed.
1498  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1499  * So for pohyhedrons some nodes can be counted several times in the returned result.
1500  * 
1501  * \return a newly allocated array
1502  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1503  */
1504 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1505 {
1506   checkConnectivityFullyDefined();
1507   int nbOfCells=getNumberOfCells();
1508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1509   ret->alloc(nbOfCells,1);
1510   int *retPtr=ret->getPointer();
1511   const int *conn=getNodalConnectivity()->getConstPointer();
1512   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1513   for(int i=0;i<nbOfCells;i++,retPtr++)
1514     {
1515       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1516         *retPtr=connI[i+1]-connI[i]-1;
1517       else
1518         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1519     }
1520   return ret.retn();
1521 }
1522
1523 /*!
1524  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1525  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1526  *
1527  * \return DataArrayInt * - new object to be deallocated by the caller.
1528  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1529  */
1530 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1531 {
1532   checkConnectivityFullyDefined();
1533   int nbOfCells=getNumberOfCells();
1534   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1535   ret->alloc(nbOfCells,1);
1536   int *retPtr=ret->getPointer();
1537   const int *conn=getNodalConnectivity()->getConstPointer();
1538   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1539   for(int i=0;i<nbOfCells;i++,retPtr++)
1540     {
1541       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1542       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1543         *retPtr=(int)s.size();
1544       else
1545         {
1546           s.erase(-1);
1547           *retPtr=(int)s.size();
1548         }
1549     }
1550   return ret.retn();
1551 }
1552
1553 /*!
1554  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1555  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1556  * 
1557  * \return a newly allocated array
1558  */
1559 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1560 {
1561   checkConnectivityFullyDefined();
1562   int nbOfCells=getNumberOfCells();
1563   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1564   ret->alloc(nbOfCells,1);
1565   int *retPtr=ret->getPointer();
1566   const int *conn=getNodalConnectivity()->getConstPointer();
1567   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1568   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1569     {
1570       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1571       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1572     }
1573   return ret.retn();
1574 }
1575
1576 /*!
1577  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1578  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1579  * array mean that the corresponding old node is no more used. 
1580  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1581  *           this->getNumberOfNodes() before call of this method. The caller is to
1582  *           delete this array using decrRef() as it is no more needed. 
1583  *  \throw If the coordinates array is not set.
1584  *  \throw If the nodal connectivity of cells is not defined.
1585  *  \throw If the nodal connectivity includes an invalid id.
1586  *
1587  *  \if ENABLE_EXAMPLES
1588  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1589  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1590  *  \endif
1591  */
1592 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1593 {
1594   return MEDCouplingPointSet::zipCoordsTraducer();
1595 }
1596
1597 /*!
1598  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1599  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1600  */
1601 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1602 {
1603   switch(compType)
1604   {
1605     case 0:
1606       return AreCellsEqual0(conn,connI,cell1,cell2);
1607     case 1:
1608       return AreCellsEqual1(conn,connI,cell1,cell2);
1609     case 2:
1610       return AreCellsEqual2(conn,connI,cell1,cell2);
1611     case 3:
1612       return AreCellsEqual3(conn,connI,cell1,cell2);
1613     case 7:
1614       return AreCellsEqual7(conn,connI,cell1,cell2);
1615   }
1616   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1617 }
1618
1619 /*!
1620  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1621  */
1622 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1623 {
1624   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1625     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1626   return 0;
1627 }
1628
1629 /*!
1630  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1631  */
1632 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1633 {
1634   int sz=connI[cell1+1]-connI[cell1];
1635   if(sz==connI[cell2+1]-connI[cell2])
1636     {
1637       if(conn[connI[cell1]]==conn[connI[cell2]])
1638         {
1639           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1640           unsigned dim=cm.getDimension();
1641           if(dim!=3)
1642             {
1643               if(dim!=1)
1644                 {
1645                   int sz1=2*(sz-1);
1646                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1647                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1648                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1649                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1650                   return work!=tmp+sz1?1:0;
1651                 }
1652               else
1653                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1654             }
1655           else
1656             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1657         }
1658     }
1659   return 0;
1660 }
1661
1662 /*!
1663  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1664  */
1665 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1666 {
1667   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1668     {
1669       if(conn[connI[cell1]]==conn[connI[cell2]])
1670         {
1671           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1672           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1673           return s1==s2?1:0;
1674         }
1675     }
1676   return 0;
1677 }
1678
1679 /*!
1680  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1681  */
1682 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1683 {
1684   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1685     {
1686       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1687       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1688       return s1==s2?1:0;
1689     }
1690   return 0;
1691 }
1692
1693 /*!
1694  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1695  */
1696 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1697 {
1698   int sz=connI[cell1+1]-connI[cell1];
1699   if(sz==connI[cell2+1]-connI[cell2])
1700     {
1701       if(conn[connI[cell1]]==conn[connI[cell2]])
1702         {
1703           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1704           unsigned dim=cm.getDimension();
1705           if(dim!=3)
1706             {
1707               if(dim!=1)
1708                 {
1709                   int sz1=2*(sz-1);
1710                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1711                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1712                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1713                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1714                   if(work!=tmp+sz1)
1715                     return 1;
1716                   else
1717                     {
1718                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1719                       std::reverse_iterator<int *> it2((int *)tmp);
1720                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1721                         return 2;
1722                       else
1723                         return 0;
1724                     }
1725
1726                   return work!=tmp+sz1?1:0;
1727                 }
1728               else
1729                 {//case of SEG2 and SEG3
1730                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1731                     return 1;
1732                   if(!cm.isQuadratic())
1733                     {
1734                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1735                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1736                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1737                         return 2;
1738                       return 0;
1739                     }
1740                   else
1741                     {
1742                       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])
1743                         return 2;
1744                       return 0;
1745                     }
1746                 }
1747             }
1748           else
1749             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1750         }
1751     }
1752   return 0;
1753 }
1754
1755 /*!
1756  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1757  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1758  * and result remains unchanged.
1759  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1760  * If in 'candidates' pool -1 value is considered as an empty value.
1761  * WARNING this method returns only ONE set of result !
1762  */
1763 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1764 {
1765   if(candidates.size()<1)
1766     return false;
1767   bool ret=false;
1768   std::vector<int>::const_iterator iter=candidates.begin();
1769   int start=(*iter++);
1770   for(;iter!=candidates.end();iter++)
1771     {
1772       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1773       if(status!=0)
1774         {
1775           if(!ret)
1776             {
1777               result->pushBackSilent(start);
1778               ret=true;
1779             }
1780           if(status==1)
1781             result->pushBackSilent(*iter);
1782           else
1783             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1784         }
1785     }
1786   return ret;
1787 }
1788
1789 /*!
1790  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1791  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1792  *
1793  * \param [in] compType input specifying the technique used to compare cells each other.
1794  *   - 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.
1795  *   - 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)
1796  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1797  *   - 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
1798  * can be used for users not sensitive to orientation of cell
1799  * \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.
1800  * \param [out] commonCells
1801  * \param [out] commonCellsI
1802  * \return the correspondance array old to new in a newly allocated array.
1803  * 
1804  */
1805 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1806 {
1807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1808   getReverseNodalConnectivity(revNodal,revNodalI);
1809   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1810 }
1811
1812 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1813                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1814 {
1815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1816   int nbOfCells=nodalI->getNumberOfTuples()-1;
1817   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1818   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1819   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1820   std::vector<bool> isFetched(nbOfCells,false);
1821   if(startCellId==0)
1822     {
1823       for(int i=0;i<nbOfCells;i++)
1824         {
1825           if(!isFetched[i])
1826             {
1827               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1828               std::vector<int> v,v2;
1829               if(connOfNode!=connPtr+connIPtr[i+1])
1830                 {
1831                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1832                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1833                   connOfNode++;
1834                 }
1835               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1836                 if(*connOfNode>=0)
1837                   {
1838                     v=v2;
1839                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1840                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1841                     v2.resize(std::distance(v2.begin(),it));
1842                   }
1843               if(v2.size()>1)
1844                 {
1845                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1846                     {
1847                       int pos=commonCellsI->back();
1848                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1849                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1850                         isFetched[*it]=true;
1851                     }
1852                 }
1853             }
1854         }
1855     }
1856   else
1857     {
1858       for(int i=startCellId;i<nbOfCells;i++)
1859         {
1860           if(!isFetched[i])
1861             {
1862               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1863               std::vector<int> v,v2;
1864               if(connOfNode!=connPtr+connIPtr[i+1])
1865                 {
1866                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1867                   connOfNode++;
1868                 }
1869               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1870                 if(*connOfNode>=0)
1871                   {
1872                     v=v2;
1873                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1874                     v2.resize(std::distance(v2.begin(),it));
1875                   }
1876               if(v2.size()>1)
1877                 {
1878                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1879                     {
1880                       int pos=commonCellsI->back();
1881                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1882                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1883                         isFetched[*it]=true;
1884                     }
1885                 }
1886             }
1887         }
1888     }
1889   commonCellsArr=commonCells.retn();
1890   commonCellsIArr=commonCellsI.retn();
1891 }
1892
1893 /*!
1894  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1895  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1896  * than \a other->getNumberOfCells() in the returned array means that there is no
1897  * corresponding cell in \a this mesh.
1898  * It is expected that \a this and \a other meshes share the same node coordinates
1899  * array, if it is not so an exception is thrown. 
1900  *  \param [in] other - the mesh to compare with.
1901  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1902  *         valid values [0,1,2], see zipConnectivityTraducer().
1903  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1904  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1905  *         values. The caller is to delete this array using
1906  *         decrRef() as it is no more needed.
1907  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1908  *         mesh.
1909  *
1910  *  \if ENABLE_EXAMPLES
1911  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1912  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1913  *  \endif
1914  *  \sa checkDeepEquivalOnSameNodesWith()
1915  *  \sa checkGeoEquivalWith()
1916  */
1917 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1918 {
1919   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1920   int nbOfCells=getNumberOfCells();
1921   static const int possibleCompType[]={0,1,2};
1922   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1923     {
1924       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1925       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1926       oss << " !";
1927       throw INTERP_KERNEL::Exception(oss.str().c_str());
1928     }
1929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1930   arr=o2n->substr(nbOfCells);
1931   arr->setName(other->getName());
1932   int tmp;
1933   if(other->getNumberOfCells()==0)
1934     return true;
1935   return arr->getMaxValue(tmp)<nbOfCells;
1936 }
1937
1938 /*!
1939  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1940  * This method tries to determine if \b other is fully included in \b this.
1941  * The main difference is that this method is not expected to throw exception.
1942  * This method has two outputs :
1943  *
1944  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1945  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1946  */
1947 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1948 {
1949   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1950   DataArrayInt *commonCells=0,*commonCellsI=0;
1951   int thisNbCells=getNumberOfCells();
1952   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1953   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1954   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1955   int otherNbCells=other->getNumberOfCells();
1956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1957   arr2->alloc(otherNbCells,1);
1958   arr2->fillWithZero();
1959   int *arr2Ptr=arr2->getPointer();
1960   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1961   for(int i=0;i<nbOfCommon;i++)
1962     {
1963       int start=commonCellsPtr[commonCellsIPtr[i]];
1964       if(start<thisNbCells)
1965         {
1966           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1967             {
1968               int sig=commonCellsPtr[j]>0?1:-1;
1969               int val=std::abs(commonCellsPtr[j])-1;
1970               if(val>=thisNbCells)
1971                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1972             }
1973         }
1974     }
1975   arr2->setName(other->getName());
1976   if(arr2->presenceOfValue(0))
1977     return false;
1978   arr=arr2.retn();
1979   return true;
1980 }
1981
1982 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1983 {
1984   if(!other)
1985     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1986   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1987   if(!otherC)
1988     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1989   std::vector<const MEDCouplingUMesh *> ms(2);
1990   ms[0]=this;
1991   ms[1]=otherC;
1992   return MergeUMeshesOnSameCoords(ms);
1993 }
1994
1995 /*!
1996  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1997  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1998  * cellIds is not given explicitely but by a range python like.
1999  * 
2000  * \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.
2001  * \return a newly allocated
2002  * 
2003  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2004  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2005  */
2006 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2007 {
2008   if(getMeshDimension()!=-1)
2009     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2010   else
2011     {
2012       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2013       if(newNbOfCells!=1)
2014         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2015       if(start!=0)
2016         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2017       incrRef();
2018       return const_cast<MEDCouplingUMesh *>(this);
2019     }
2020 }
2021
2022 /*!
2023  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2024  * The result mesh shares or not the node coordinates array with \a this mesh depending
2025  * on \a keepCoords parameter.
2026  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2027  *           to write this mesh to the MED file, its cells must be sorted using
2028  *           sortCellsInMEDFileFrmt().
2029  *  \param [in] begin - an array of cell ids to include to the new mesh.
2030  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2031  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2032  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2033  *         by calling zipCoords().
2034  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2035  *         to delete this mesh using decrRef() as it is no more needed. 
2036  *  \throw If the coordinates array is not set.
2037  *  \throw If the nodal connectivity of cells is not defined.
2038  *  \throw If any cell id in the array \a begin is not valid.
2039  *
2040  *  \if ENABLE_EXAMPLES
2041  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2042  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2043  *  \endif
2044  */
2045 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2046 {
2047   if(getMeshDimension()!=-1)
2048     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2049   else
2050     {
2051       if(end-begin!=1)
2052         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2053       if(begin[0]!=0)
2054         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2055       incrRef();
2056       return const_cast<MEDCouplingUMesh *>(this);
2057     }
2058 }
2059
2060 /*!
2061  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2062  *
2063  * 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.
2064  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2065  * The number of cells of \b this will remain the same with this method.
2066  *
2067  * \param [in] begin begin of cell ids (included) of cells in this to assign
2068  * \param [in] end end of cell ids (excluded) of cells in this to assign
2069  * \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 ).
2070  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2071  */
2072 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2073 {
2074   checkConnectivityFullyDefined();
2075   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2076   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2077     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2078   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2079     {
2080       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2081       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2082       throw INTERP_KERNEL::Exception(oss.str().c_str());
2083     }
2084   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2085   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2086     {
2087       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2088       throw INTERP_KERNEL::Exception(oss.str().c_str());
2089     }
2090   int nbOfCells=getNumberOfCells();
2091   bool easyAssign=true;
2092   const int *connI=_nodal_connec_index->getConstPointer();
2093   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2094   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2095     {
2096       if(*it>=0 && *it<nbOfCells)
2097         {
2098           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2099         }
2100       else
2101         {
2102           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2103           throw INTERP_KERNEL::Exception(oss.str().c_str());
2104         }
2105     }
2106   if(easyAssign)
2107     {
2108       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2109       computeTypes();
2110     }
2111   else
2112     {
2113       DataArrayInt *arrOut=0,*arrIOut=0;
2114       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2115                                                arrOut,arrIOut);
2116       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2117       setConnectivity(arrOut,arrIOut,true);
2118     }
2119 }
2120
2121 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2122 {
2123   checkConnectivityFullyDefined();
2124   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2125   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2126     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2127   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2128     {
2129       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2130       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2131       throw INTERP_KERNEL::Exception(oss.str().c_str());
2132     }
2133   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2134   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2135     {
2136       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2137       throw INTERP_KERNEL::Exception(oss.str().c_str());
2138     }
2139   int nbOfCells=getNumberOfCells();
2140   bool easyAssign=true;
2141   const int *connI=_nodal_connec_index->getConstPointer();
2142   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2143   int it=start;
2144   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2145     {
2146       if(it>=0 && it<nbOfCells)
2147         {
2148           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2149         }
2150       else
2151         {
2152           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2153           throw INTERP_KERNEL::Exception(oss.str().c_str());
2154         }
2155     }
2156   if(easyAssign)
2157     {
2158       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2159       computeTypes();
2160     }
2161   else
2162     {
2163       DataArrayInt *arrOut=0,*arrIOut=0;
2164       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2165                                                 arrOut,arrIOut);
2166       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2167       setConnectivity(arrOut,arrIOut,true);
2168     }
2169 }                      
2170
2171 /*!
2172  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2173  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2174  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2175  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2176  *
2177  * \param [in] begin input start of array of node ids.
2178  * \param [in] end input end of array of node ids.
2179  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2180  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2181  */
2182 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2183 {
2184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2185   checkConnectivityFullyDefined();
2186   int tmp=-1;
2187   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2188   std::vector<bool> fastFinder(sz,false);
2189   for(const int *work=begin;work!=end;work++)
2190     if(*work>=0 && *work<sz)
2191       fastFinder[*work]=true;
2192   int nbOfCells=getNumberOfCells();
2193   const int *conn=getNodalConnectivity()->getConstPointer();
2194   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2195   for(int i=0;i<nbOfCells;i++)
2196     {
2197       int ref=0,nbOfHit=0;
2198       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2199         if(*work2>=0)
2200           {
2201             ref++;
2202             if(fastFinder[*work2])
2203               nbOfHit++;
2204           }
2205       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2206         cellIdsKept->pushBackSilent(i);
2207     }
2208   cellIdsKeptArr=cellIdsKept.retn();
2209 }
2210
2211 /*!
2212  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2213  * this->getMeshDimension(), that bound some cells of \a this mesh.
2214  * The cells of lower dimension to include to the result mesh are selected basing on
2215  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2216  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2217  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2218  * created mesh shares the node coordinates array with \a this mesh. 
2219  *  \param [in] begin - the array of node ids.
2220  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2221  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2222  *         array \a begin are added, else cells whose any node is in the
2223  *         array \a begin are added.
2224  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2225  *         to delete this mesh using decrRef() as it is no more needed. 
2226  *  \throw If the coordinates array is not set.
2227  *  \throw If the nodal connectivity of cells is not defined.
2228  *  \throw If any node id in \a begin is not valid.
2229  *
2230  *  \if ENABLE_EXAMPLES
2231  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2232  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2233  *  \endif
2234  */
2235 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2236 {
2237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2238   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2239   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2240   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2241   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2242 }
2243
2244 /*!
2245  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2246  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2247  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2248  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2249  *         by calling zipCoords().
2250  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2251  *         to delete this mesh using decrRef() as it is no more needed. 
2252  *  \throw If the coordinates array is not set.
2253  *  \throw If the nodal connectivity of cells is not defined.
2254  *
2255  *  \if ENABLE_EXAMPLES
2256  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2257  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2258  *  \endif
2259  */
2260 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2261 {
2262   DataArrayInt *desc=DataArrayInt::New();
2263   DataArrayInt *descIndx=DataArrayInt::New();
2264   DataArrayInt *revDesc=DataArrayInt::New();
2265   DataArrayInt *revDescIndx=DataArrayInt::New();
2266   //
2267   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2268   revDesc->decrRef();
2269   desc->decrRef();
2270   descIndx->decrRef();
2271   int nbOfCells=meshDM1->getNumberOfCells();
2272   const int *revDescIndxC=revDescIndx->getConstPointer();
2273   std::vector<int> boundaryCells;
2274   for(int i=0;i<nbOfCells;i++)
2275     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2276       boundaryCells.push_back(i);
2277   revDescIndx->decrRef();
2278   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2279   return ret;
2280 }
2281
2282 /*!
2283  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2284  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2285  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2286  */
2287 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2288 {
2289   checkFullyDefined();
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2292   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2293   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2294   //
2295   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2296   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2297   //
2298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2300   const int *revDescPtr=revDesc->getConstPointer();
2301   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2302   int nbOfCells=getNumberOfCells();
2303   std::vector<bool> ret1(nbOfCells,false);
2304   int sz=0;
2305   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2306     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2307       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2308   //
2309   DataArrayInt *ret2=DataArrayInt::New();
2310   ret2->alloc(sz,1);
2311   int *ret2Ptr=ret2->getPointer();
2312   sz=0;
2313   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2314     if(*it)
2315       *ret2Ptr++=sz;
2316   ret2->setName("BoundaryCells");
2317   return ret2;
2318 }
2319
2320 /*!
2321  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2322  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2323  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2324  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2325  *
2326  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2327  * This method method returns cells ids set s = s1 + s2 where :
2328  * 
2329  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2330  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2331  *
2332  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2333  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2334  *
2335  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2336  * \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
2337  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2338  */
2339 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2340 {
2341   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2343   checkConnectivityFullyDefined();
2344   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2345   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2346     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2349   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2350   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2351   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2352   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2353   DataArrayInt *idsOtherInConsti=0;
2354   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2356   if(!b)
2357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2358   std::set<int> s1;
2359   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2360     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2363   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2364   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2366   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2367   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2368   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2369   neighThisPartAuto=0;
2370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2371   const int li[2]={0,1};
2372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2373   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2375   s_renum1->sort();
2376   //
2377   cellIdsRk0=s0arr.retn();
2378   cellIdsRk1=s_renum1.retn();
2379 }
2380
2381 /*!
2382  * 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
2383  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2384  * 
2385  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2386  */
2387 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2388 {
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2393   //
2394   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2395   revDesc=0; desc=0; descIndx=0;
2396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2397   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2398   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2399 }
2400
2401 /*!
2402  * Finds nodes lying on the boundary of \a this mesh.
2403  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2404  *          nodes. The caller is to delete this array using decrRef() as it is no
2405  *          more needed.
2406  *  \throw If the coordinates array is not set.
2407  *  \throw If the nodal connectivity of cells is node defined.
2408  *
2409  *  \if ENABLE_EXAMPLES
2410  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2411  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2412  *  \endif
2413  */
2414 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2415 {
2416   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2417   return skin->computeFetchedNodeIds();
2418 }
2419
2420 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2421 {
2422   incrRef();
2423   return const_cast<MEDCouplingUMesh *>(this);
2424 }
2425
2426 /*!
2427  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2428  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2429  * 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.
2430  * 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.
2431  * 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.
2432  *
2433  * \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
2434  *             parameter is altered during the call.
2435  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2436  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2437  * \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.
2438  *
2439  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2440  */
2441 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2442                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2443 {
2444   checkFullyDefined();
2445   otherDimM1OnSameCoords.checkFullyDefined();
2446   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2447     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2448   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2449     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2450   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2451   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2452   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2454   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2455   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2459   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2460   //
2461   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2463   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2464   DataArrayInt *idsTmp=0;
2465   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2467   if(!b)
2468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2469   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2470   DataArrayInt *tmp0=0,*tmp1=0;
2471   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2473   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2474   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2475   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2476   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2477   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2478   //
2479   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2480   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2481   nodeIdsToDuplicate=s3.retn();
2482 }
2483
2484 /*!
2485  * This method operates a modification of the connectivity and coords in \b this.
2486  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2487  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2488  * 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
2489  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2490  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2491  * 
2492  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2493  * 
2494  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2495  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2496  */
2497 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2498 {
2499   int nbOfNodes=getNumberOfNodes();
2500   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2501   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2502 }
2503
2504 /*!
2505  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2506  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2507  * This method is a generalization of shiftNodeNumbersInConn().
2508  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2509  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2510  *         this->getNumberOfNodes(), in "Old to New" mode. 
2511  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2512  *  \throw If the nodal connectivity of cells is not defined.
2513  *
2514  *  \if ENABLE_EXAMPLES
2515  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2516  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2517  *  \endif
2518  */
2519 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2520 {
2521   checkConnectivityFullyDefined();
2522   int *conn=getNodalConnectivity()->getPointer();
2523   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2524   int nbOfCells=getNumberOfCells();
2525   for(int i=0;i<nbOfCells;i++)
2526     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2527       {
2528         int& node=conn[iconn];
2529         if(node>=0)//avoid polyhedron separator
2530           {
2531             node=newNodeNumbersO2N[node];
2532           }
2533       }
2534   _nodal_connec->declareAsNew();
2535   updateTime();
2536 }
2537
2538 /*!
2539  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2540  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2541  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2542  * 
2543  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2544  */
2545 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2546 {
2547   checkConnectivityFullyDefined();
2548   int *conn=getNodalConnectivity()->getPointer();
2549   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2550   int nbOfCells=getNumberOfCells();
2551   for(int i=0;i<nbOfCells;i++)
2552     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2553       {
2554         int& node=conn[iconn];
2555         if(node>=0)//avoid polyhedron separator
2556           {
2557             node+=delta;
2558           }
2559       }
2560   _nodal_connec->declareAsNew();
2561   updateTime();
2562 }
2563
2564 /*!
2565  * This method operates a modification of the connectivity in \b this.
2566  * 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.
2567  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2568  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2569  * 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
2570  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2571  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2572  * 
2573  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2574  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2575  * 
2576  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2577  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2578  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2579  */
2580 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2581 {
2582   checkConnectivityFullyDefined();
2583   std::map<int,int> m;
2584   int val=offset;
2585   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2586     m[*work]=val;
2587   int *conn=getNodalConnectivity()->getPointer();
2588   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2589   int nbOfCells=getNumberOfCells();
2590   for(int i=0;i<nbOfCells;i++)
2591     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2592       {
2593         int& node=conn[iconn];
2594         if(node>=0)//avoid polyhedron separator
2595           {
2596             std::map<int,int>::iterator it=m.find(node);
2597             if(it!=m.end())
2598               node=(*it).second;
2599           }
2600       }
2601   updateTime();
2602 }
2603
2604 /*!
2605  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2606  *
2607  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2608  * After the call of this method the number of cells remains the same as before.
2609  *
2610  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2611  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2612  * be strictly in [0;this->getNumberOfCells()).
2613  *
2614  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2615  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2616  * should be contained in[0;this->getNumberOfCells()).
2617  * 
2618  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2619  */
2620 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2621 {
2622   checkConnectivityFullyDefined();
2623   int nbCells=getNumberOfCells();
2624   const int *array=old2NewBg;
2625   if(check)
2626     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2627   //
2628   const int *conn=_nodal_connec->getConstPointer();
2629   const int *connI=_nodal_connec_index->getConstPointer();
2630   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2632   const int *n2oPtr=n2o->begin();
2633   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2634   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2635   newConn->copyStringInfoFrom(*_nodal_connec);
2636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2637   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2638   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2639   //
2640   int *newC=newConn->getPointer();
2641   int *newCI=newConnI->getPointer();
2642   int loc=0;
2643   newCI[0]=loc;
2644   for(int i=0;i<nbCells;i++)
2645     {
2646       int pos=n2oPtr[i];
2647       int nbOfElts=connI[pos+1]-connI[pos];
2648       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2649       loc+=nbOfElts;
2650       newCI[i+1]=loc;
2651     }
2652   //
2653   setConnectivity(newConn,newConnI);
2654   if(check)
2655     free(const_cast<int *>(array));
2656 }
2657
2658 /*!
2659  * Finds cells whose bounding boxes intersect a given bounding box.
2660  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2661  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2662  *         zMax (if in 3D). 
2663  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2664  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2665  *         extent of the bounding box of cell to produce an addition to this bounding box.
2666  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2667  *         cells. The caller is to delete this array using decrRef() as it is no more
2668  *         needed. 
2669  *  \throw If the coordinates array is not set.
2670  *  \throw If the nodal connectivity of cells is not defined.
2671  *
2672  *  \if ENABLE_EXAMPLES
2673  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2674  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2675  *  \endif
2676  */
2677 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2678 {
2679   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2680   if(getMeshDimension()==-1)
2681     {
2682       elems->pushBackSilent(0);
2683       return elems.retn();
2684     }
2685   int dim=getSpaceDimension();
2686   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2687   const int* conn      = getNodalConnectivity()->getConstPointer();
2688   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2689   const double* coords = getCoords()->getConstPointer();
2690   int nbOfCells=getNumberOfCells();
2691   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2692     {
2693       for (int i=0; i<dim; i++)
2694         {
2695           elem_bb[i*2]=std::numeric_limits<double>::max();
2696           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2697         }
2698
2699       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2700         {
2701           int node= conn[inode];
2702           if(node>=0)//avoid polyhedron separator
2703             {
2704               for (int idim=0; idim<dim; idim++)
2705                 {
2706                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2707                     {
2708                       elem_bb[idim*2] = coords[node*dim+idim] ;
2709                     }
2710                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2711                     {
2712                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2713                     }
2714                 }
2715             }
2716         }
2717       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2718         elems->pushBackSilent(ielem);
2719     }
2720   return elems.retn();
2721 }
2722
2723 /*!
2724  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2725  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2726  * added in 'elems' parameter.
2727  */
2728 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2729 {
2730   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2731   if(getMeshDimension()==-1)
2732     {
2733       elems->pushBackSilent(0);
2734       return elems.retn();
2735     }
2736   int dim=getSpaceDimension();
2737   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2738   const int* conn      = getNodalConnectivity()->getConstPointer();
2739   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2740   const double* coords = getCoords()->getConstPointer();
2741   int nbOfCells=getNumberOfCells();
2742   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2743     {
2744       for (int i=0; i<dim; i++)
2745         {
2746           elem_bb[i*2]=std::numeric_limits<double>::max();
2747           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2748         }
2749
2750       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2751         {
2752           int node= conn[inode];
2753           if(node>=0)//avoid polyhedron separator
2754             {
2755               for (int idim=0; idim<dim; idim++)
2756                 {
2757                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2758                     {
2759                       elem_bb[idim*2] = coords[node*dim+idim] ;
2760                     }
2761                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2762                     {
2763                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2764                     }
2765                 }
2766             }
2767         }
2768       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2769         elems->pushBackSilent(ielem);
2770     }
2771   return elems.retn();
2772 }
2773
2774 /*!
2775  * Returns a type of a cell by its id.
2776  *  \param [in] cellId - the id of the cell of interest.
2777  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2778  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2779  */
2780 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2781 {
2782   const int *ptI=_nodal_connec_index->getConstPointer();
2783   const int *pt=_nodal_connec->getConstPointer();
2784   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2785     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2786   else
2787     {
2788       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2789       throw INTERP_KERNEL::Exception(oss.str().c_str());
2790     }
2791 }
2792
2793 /*!
2794  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2795  * This method does not throw exception if geometric type \a type is not in \a this.
2796  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2797  * The coordinates array is not considered here.
2798  *
2799  * \param [in] type the geometric type
2800  * \return cell ids in this having geometric type \a type.
2801  */
2802 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2803 {
2804
2805   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2806   ret->alloc(0,1);
2807   checkConnectivityFullyDefined();
2808   int nbCells=getNumberOfCells();
2809   int mdim=getMeshDimension();
2810   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2811   if(mdim!=(int)cm.getDimension())
2812     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2813   const int *ptI=_nodal_connec_index->getConstPointer();
2814   const int *pt=_nodal_connec->getConstPointer();
2815   for(int i=0;i<nbCells;i++)
2816     {
2817       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2818         ret->pushBackSilent(i);
2819     }
2820   return ret.retn();
2821 }
2822
2823 /*!
2824  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2825  */
2826 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2827 {
2828   const int *ptI=_nodal_connec_index->getConstPointer();
2829   const int *pt=_nodal_connec->getConstPointer();
2830   int nbOfCells=getNumberOfCells();
2831   int ret=0;
2832   for(int i=0;i<nbOfCells;i++)
2833     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2834       ret++;
2835   return ret;
2836 }
2837
2838 /*!
2839  * Returns the nodal connectivity of a given cell.
2840  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2841  * all returned node ids can be used in getCoordinatesOfNode().
2842  *  \param [in] cellId - an id of the cell of interest.
2843  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2844  *         cleared before the appending.
2845  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2846  */
2847 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2848 {
2849   const int *ptI=_nodal_connec_index->getConstPointer();
2850   const int *pt=_nodal_connec->getConstPointer();
2851   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2852     if(*w>=0)
2853       conn.push_back(*w);
2854 }
2855
2856 std::string MEDCouplingUMesh::simpleRepr() const
2857 {
2858   static const char msg0[]="No coordinates specified !";
2859   std::ostringstream ret;
2860   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2861   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2862   int tmpp1,tmpp2;
2863   double tt=getTime(tmpp1,tmpp2);
2864   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2865   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2866   if(_mesh_dim>=-1)
2867     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2868   else
2869     { ret << " Mesh dimension has not been set or is invalid !"; }
2870   if(_coords!=0)
2871     {
2872       const int spaceDim=getSpaceDimension();
2873       ret << spaceDim << "\nInfo attached on space dimension : ";
2874       for(int i=0;i<spaceDim;i++)
2875         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2876       ret << "\n";
2877     }
2878   else
2879     ret << msg0 << "\n";
2880   ret << "Number of nodes : ";
2881   if(_coords!=0)
2882     ret << getNumberOfNodes() << "\n";
2883   else
2884     ret << msg0 << "\n";
2885   ret << "Number of cells : ";
2886   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2887     ret << getNumberOfCells() << "\n";
2888   else
2889     ret << "No connectivity specified !" << "\n";
2890   ret << "Cell types present : ";
2891   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2892     {
2893       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2894       ret << cm.getRepr() << " ";
2895     }
2896   ret << "\n";
2897   return ret.str();
2898 }
2899
2900 std::string MEDCouplingUMesh::advancedRepr() const
2901 {
2902   std::ostringstream ret;
2903   ret << simpleRepr();
2904   ret << "\nCoordinates array : \n___________________\n\n";
2905   if(_coords)
2906     _coords->reprWithoutNameStream(ret);
2907   else
2908     ret << "No array set !\n";
2909   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2910   reprConnectivityOfThisLL(ret);
2911   return ret.str();
2912 }
2913
2914 /*!
2915  * This method returns a C++ code that is a dump of \a this.
2916  * This method will throw if this is not fully defined.
2917  */
2918 std::string MEDCouplingUMesh::cppRepr() const
2919 {
2920   static const char coordsName[]="coords";
2921   static const char connName[]="conn";
2922   static const char connIName[]="connI";
2923   checkFullyDefined();
2924   std::ostringstream ret; ret << "// coordinates" << std::endl;
2925   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2926   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2927   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2928   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2929   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2930   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2931   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2932   return ret.str();
2933 }
2934
2935 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2936 {
2937   std::ostringstream ret;
2938   reprConnectivityOfThisLL(ret);
2939   return ret.str();
2940 }
2941
2942 /*!
2943  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2944  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2945  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2946  * some algos).
2947  * 
2948  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2949  * 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
2950  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2951  */
2952 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2953 {
2954   int mdim=getMeshDimension();
2955   if(mdim<0)
2956     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2957   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2958   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2959   bool needToCpyCT=true;
2960   if(!_nodal_connec)
2961     {
2962       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2963       needToCpyCT=false;
2964     }
2965   else
2966     {
2967       tmp1=_nodal_connec;
2968       tmp1->incrRef();
2969     }
2970   if(!_nodal_connec_index)
2971     {
2972       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2973       needToCpyCT=false;
2974     }
2975   else
2976     {
2977       tmp2=_nodal_connec_index;
2978       tmp2->incrRef();
2979     }
2980   ret->setConnectivity(tmp1,tmp2,false);
2981   if(needToCpyCT)
2982     ret->_types=_types;
2983   if(!_coords)
2984     {
2985       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2986       ret->setCoords(coords);
2987     }
2988   else
2989     ret->setCoords(_coords);
2990   return ret.retn();
2991 }
2992
2993 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2994 {
2995   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2996     {
2997       int nbOfCells=getNumberOfCells();
2998       const int *c=_nodal_connec->getConstPointer();
2999       const int *ci=_nodal_connec_index->getConstPointer();
3000       for(int i=0;i<nbOfCells;i++)
3001         {
3002           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3003           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3004           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3005           stream << "\n";
3006         }
3007     }
3008   else
3009     stream << "Connectivity not defined !\n";
3010 }
3011
3012 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3013 {
3014   const int *ptI=_nodal_connec_index->getConstPointer();
3015   const int *pt=_nodal_connec->getConstPointer();
3016   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3017     return ptI[cellId+1]-ptI[cellId]-1;
3018   else
3019     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3020 }
3021
3022 /*!
3023  * Returns types of cells of the specified part of \a this mesh.
3024  * This method avoids computing sub-mesh explicitely to get its types.
3025  *  \param [in] begin - an array of cell ids of interest.
3026  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3027  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3028  *         describing the cell types. 
3029  *  \throw If the coordinates array is not set.
3030  *  \throw If the nodal connectivity of cells is not defined.
3031  *  \sa getAllGeoTypes()
3032  */
3033 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3034 {
3035   checkFullyDefined();
3036   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3037   const int *conn=_nodal_connec->getConstPointer();
3038   const int *connIndex=_nodal_connec_index->getConstPointer();
3039   for(const int *w=begin;w!=end;w++)
3040     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3041   return ret;
3042 }
3043
3044 /*!
3045  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3046  * a set of types of cells constituting \a this mesh. 
3047  * This method is for advanced users having prepared their connectivity before. For
3048  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3049  *  \param [in] conn - the nodal connectivity array. 
3050  *  \param [in] connIndex - the nodal connectivity index array.
3051  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3052  *         mesh is updated.
3053  */
3054 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3055 {
3056   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3057   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3058   if(isComputingTypes)
3059     computeTypes();
3060   declareAsNew();
3061 }
3062
3063 /*!
3064  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3065  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3066  */
3067 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3068     _nodal_connec(0),_nodal_connec_index(0),
3069     _types(other._types)
3070 {
3071   if(other._nodal_connec)
3072     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3073   if(other._nodal_connec_index)
3074     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3075 }
3076
3077 MEDCouplingUMesh::~MEDCouplingUMesh()
3078 {
3079   if(_nodal_connec)
3080     _nodal_connec->decrRef();
3081   if(_nodal_connec_index)
3082     _nodal_connec_index->decrRef();
3083 }
3084
3085 /*!
3086  * Recomputes a set of cell types of \a this mesh. For more info see
3087  * \ref MEDCouplingUMeshNodalConnectivity.
3088  */
3089 void MEDCouplingUMesh::computeTypes()
3090 {
3091   if(_nodal_connec && _nodal_connec_index)
3092     {
3093       _types.clear();
3094       const int *conn=_nodal_connec->getConstPointer();
3095       const int *connIndex=_nodal_connec_index->getConstPointer();
3096       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3097       if (nbOfElem > 0)
3098         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3099           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3100     }
3101 }
3102
3103 /*!
3104  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3105  */
3106 void MEDCouplingUMesh::checkFullyDefined() const
3107 {
3108   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3109     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3110 }
3111
3112 /*!
3113  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3114  */
3115 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3116 {
3117   if(!_nodal_connec_index || !_nodal_connec)
3118     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3119 }
3120
3121 /*!
3122  * Returns a number of cells constituting \a this mesh. 
3123  *  \return int - the number of cells in \a this mesh.
3124  *  \throw If the nodal connectivity of cells is not defined.
3125  */
3126 int MEDCouplingUMesh::getNumberOfCells() const
3127
3128   if(_nodal_connec_index)
3129     return _nodal_connec_index->getNumberOfTuples()-1;
3130   else
3131     if(_mesh_dim==-1)
3132       return 1;
3133     else
3134       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3135 }
3136
3137 /*!
3138  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3139  * mesh. For more info see \ref MEDCouplingMeshesPage.
3140  *  \return int - the dimension of \a this mesh.
3141  *  \throw If the mesh dimension is not defined using setMeshDimension().
3142  */
3143 int MEDCouplingUMesh::getMeshDimension() const
3144 {
3145   if(_mesh_dim<-1)
3146     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3147   return _mesh_dim;
3148 }
3149
3150 /*!
3151  * Returns a length of the nodal connectivity array.
3152  * This method is for test reason. Normally the integer returned is not useable by
3153  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3154  *  \return int - the length of the nodal connectivity array.
3155  */
3156 int MEDCouplingUMesh::getMeshLength() const
3157 {
3158   return _nodal_connec->getNbOfElems();
3159 }
3160
3161 /*!
3162  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3163  */
3164 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3165 {
3166   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3167   tinyInfo.push_back(getMeshDimension());
3168   tinyInfo.push_back(getNumberOfCells());
3169   if(_nodal_connec)
3170     tinyInfo.push_back(getMeshLength());
3171   else
3172     tinyInfo.push_back(-1);
3173 }
3174
3175 /*!
3176  * First step of unserialization process.
3177  */
3178 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3179 {
3180   return tinyInfo[6]<=0;
3181 }
3182
3183 /*!
3184  * Second step of serialization process.
3185  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3186  */
3187 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3188 {
3189   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3190   if(tinyInfo[5]!=-1)
3191     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3192 }
3193
3194 /*!
3195  * Third and final step of serialization process.
3196  */
3197 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3198 {
3199   MEDCouplingPointSet::serialize(a1,a2);
3200   if(getMeshDimension()>-1)
3201     {
3202       a1=DataArrayInt::New();
3203       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3204       int *ptA1=a1->getPointer();
3205       const int *conn=getNodalConnectivity()->getConstPointer();
3206       const int *index=getNodalConnectivityIndex()->getConstPointer();
3207       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3208       std::copy(conn,conn+getMeshLength(),ptA1);
3209     }
3210   else
3211     a1=0;
3212 }
3213
3214 /*!
3215  * Second and final unserialization process.
3216  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3217  */
3218 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3219 {
3220   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3221   setMeshDimension(tinyInfo[5]);
3222   if(tinyInfo[7]!=-1)
3223     {
3224       // Connectivity
3225       const int *recvBuffer=a1->getConstPointer();
3226       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3227       myConnecIndex->alloc(tinyInfo[6]+1,1);
3228       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3229       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3230       myConnec->alloc(tinyInfo[7],1);
3231       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3232       setConnectivity(myConnec, myConnecIndex);
3233     }
3234 }
3235
3236 /*!
3237  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3238  * CellIds are given using range specified by a start an end and step.
3239  */
3240 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3241 {
3242   checkFullyDefined();
3243   int ncell=getNumberOfCells();
3244   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3245   ret->_mesh_dim=_mesh_dim;
3246   ret->setCoords(_coords);
3247   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3249   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3250   int work=start;
3251   const int *conn=_nodal_connec->getConstPointer();
3252   const int *connIndex=_nodal_connec_index->getConstPointer();
3253   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3254     {
3255       if(work>=0 && work<ncell)
3256         {
3257           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3258         }
3259       else
3260         {
3261           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3262           throw INTERP_KERNEL::Exception(oss.str().c_str());
3263         }
3264     }
3265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3266   int *newConnPtr=newConn->getPointer();
3267   std::set<INTERP_KERNEL::NormalizedCellType> types;
3268   work=start;
3269   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3270     {
3271       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3272       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3273     }
3274   ret->setConnectivity(newConn,newConnI,false);
3275   ret->_types=types;
3276   ret->copyTinyInfoFrom(this);
3277   return ret.retn();
3278 }
3279
3280 /*!
3281  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3282  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3283  * The return newly allocated mesh will share the same coordinates as \a this.
3284  */
3285 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3286 {
3287   checkConnectivityFullyDefined();
3288   int ncell=getNumberOfCells();
3289   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3290   ret->_mesh_dim=_mesh_dim;
3291   ret->setCoords(_coords);
3292   std::size_t nbOfElemsRet=std::distance(begin,end);
3293   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3294   connIndexRet[0]=0;
3295   const int *conn=_nodal_connec->getConstPointer();
3296   const int *connIndex=_nodal_connec_index->getConstPointer();
3297   int newNbring=0;
3298   for(const int *work=begin;work!=end;work++,newNbring++)
3299     {
3300       if(*work>=0 && *work<ncell)
3301         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3302       else
3303         {
3304           free(connIndexRet);
3305           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3306           throw INTERP_KERNEL::Exception(oss.str().c_str());
3307         }
3308     }
3309   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3310   int *connRetWork=connRet;
3311   std::set<INTERP_KERNEL::NormalizedCellType> types;
3312   for(const int *work=begin;work!=end;work++)
3313     {
3314       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3315       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3316     }
3317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3318   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3320   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3321   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3322   ret->_types=types;
3323   ret->copyTinyInfoFrom(this);
3324   return ret.retn();
3325 }
3326
3327 /*!
3328  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3329  * mesh.<br>
3330  * For 1D cells, the returned field contains lengths.<br>
3331  * For 2D cells, the returned field contains areas.<br>
3332  * For 3D cells, the returned field contains volumes.
3333  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3334  *         orientation, i.e. the volume is always positive.
3335  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3336  *         and one time . The caller is to delete this field using decrRef() as it is no
3337  *         more needed.
3338  */
3339 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3340 {
3341   std::string name="MeasureOfMesh_";
3342   name+=getName();
3343   int nbelem=getNumberOfCells();
3344   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3345   field->setName(name);
3346   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3347   array->alloc(nbelem,1);
3348   double *area_vol=array->getPointer();
3349   field->setArray(array) ; array=0;
3350   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3351   field->synchronizeTimeWithMesh();
3352   if(getMeshDimension()!=-1)
3353     {
3354       int ipt;
3355       INTERP_KERNEL::NormalizedCellType type;
3356       int dim_space=getSpaceDimension();
3357       const double *coords=getCoords()->getConstPointer();
3358       const int *connec=getNodalConnectivity()->getConstPointer();
3359       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3360       for(int iel=0;iel<nbelem;iel++)
3361         {
3362           ipt=connec_index[iel];
3363           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3364           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);
3365         }
3366       if(isAbs)
3367         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3368     }
3369   else
3370     {
3371       area_vol[0]=std::numeric_limits<double>::max();
3372     }
3373   return field.retn();
3374 }
3375
3376 /*!
3377  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3378  * mesh.<br>
3379  * For 1D cells, the returned array contains lengths.<br>
3380  * For 2D cells, the returned array contains areas.<br>
3381  * For 3D cells, the returned array contains volumes.
3382  * This method avoids building explicitly a part of \a this mesh to perform the work.
3383  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3384  *         orientation, i.e. the volume is always positive.
3385  *  \param [in] begin - an array of cell ids of interest.
3386  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3387  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3388  *          delete this array using decrRef() as it is no more needed.
3389  * 
3390  *  \if ENABLE_EXAMPLES
3391  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3392  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3393  *  \endif
3394  *  \sa getMeasureField()
3395  */
3396 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3397 {
3398   std::string name="PartMeasureOfMesh_";
3399   name+=getName();
3400   int nbelem=(int)std::distance(begin,end);
3401   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3402   array->setName(name);
3403   array->alloc(nbelem,1);
3404   double *area_vol=array->getPointer();
3405   if(getMeshDimension()!=-1)
3406     {
3407       int ipt;
3408       INTERP_KERNEL::NormalizedCellType type;
3409       int dim_space=getSpaceDimension();
3410       const double *coords=getCoords()->getConstPointer();
3411       const int *connec=getNodalConnectivity()->getConstPointer();
3412       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3413       for(const int *iel=begin;iel!=end;iel++)
3414         {
3415           ipt=connec_index[*iel];
3416           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3417           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3418         }
3419       if(isAbs)
3420         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3421     }
3422   else
3423     {
3424       area_vol[0]=std::numeric_limits<double>::max();
3425     }
3426   return array.retn();
3427 }
3428
3429 /*!
3430  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3431  * \a this one. The returned field contains the dual cell volume for each corresponding
3432  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3433  *  the dual mesh in P1 sens of \a this.<br>
3434  * For 1D cells, the returned field contains lengths.<br>
3435  * For 2D cells, the returned field contains areas.<br>
3436  * For 3D cells, the returned field contains volumes.
3437  * This method is useful to check "P1*" conservative interpolators.
3438  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3439  *         orientation, i.e. the volume is always positive.
3440  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3441  *          nodes and one time. The caller is to delete this array using decrRef() as
3442  *          it is no more needed.
3443  */
3444 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3445 {
3446   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3447   std::string name="MeasureOnNodeOfMesh_";
3448   name+=getName();
3449   int nbNodes=getNumberOfNodes();
3450   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3451   double cst=1./((double)getMeshDimension()+1.);
3452   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3453   array->alloc(nbNodes,1);
3454   double *valsToFill=array->getPointer();
3455   std::fill(valsToFill,valsToFill+nbNodes,0.);
3456   const double *values=tmp->getArray()->getConstPointer();
3457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3459   getReverseNodalConnectivity(da,daInd);
3460   const int *daPtr=da->getConstPointer();
3461   const int *daIPtr=daInd->getConstPointer();
3462   for(int i=0;i<nbNodes;i++)
3463     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3464       valsToFill[i]+=cst*values[*cell];
3465   ret->setMesh(this);
3466   ret->setArray(array);
3467   return ret.retn();
3468 }
3469
3470 /*!
3471  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3472  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3473  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3474  * and are normalized.
3475  * <br> \a this can be either 
3476  * - a  2D mesh in 2D or 3D space or 
3477  * - an 1D mesh in 2D space.
3478  * 
3479  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3480  *          cells and one time. The caller is to delete this field using decrRef() as
3481  *          it is no more needed.
3482  *  \throw If the nodal connectivity of cells is not defined.
3483  *  \throw If the coordinates array is not set.
3484  *  \throw If the mesh dimension is not set.
3485  *  \throw If the mesh and space dimension is not as specified above.
3486  */
3487 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3488 {
3489   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3490     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3491   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3492   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3493   int nbOfCells=getNumberOfCells();
3494   int nbComp=getMeshDimension()+1;
3495   array->alloc(nbOfCells,nbComp);
3496   double *vals=array->getPointer();
3497   const int *connI=_nodal_connec_index->getConstPointer();
3498   const int *conn=_nodal_connec->getConstPointer();
3499   const double *coords=_coords->getConstPointer();
3500   if(getMeshDimension()==2)
3501     {
3502       if(getSpaceDimension()==3)
3503         {
3504           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3505           const double *locPtr=loc->getConstPointer();
3506           for(int i=0;i<nbOfCells;i++,vals+=3)
3507             {
3508               int offset=connI[i];
3509               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3510               double n=INTERP_KERNEL::norm<3>(vals);
3511               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3512             }
3513         }
3514       else
3515         {
3516           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3517           const double *isAbsPtr=isAbs->getArray()->begin();
3518           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3519             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3520         }
3521     }
3522   else//meshdimension==1
3523     {
3524       double tmp[2];
3525       for(int i=0;i<nbOfCells;i++)
3526         {
3527           int offset=connI[i];
3528           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3529           double n=INTERP_KERNEL::norm<2>(tmp);
3530           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3531           *vals++=-tmp[1];
3532           *vals++=tmp[0];
3533         }
3534     }
3535   ret->setArray(array);
3536   ret->setMesh(this);
3537   ret->synchronizeTimeWithSupport();
3538   return ret.retn();
3539 }
3540
3541 /*!
3542  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3543  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3544  * and are normalized.
3545  * <br> \a this can be either 
3546  * - a  2D mesh in 2D or 3D space or 
3547  * - an 1D mesh in 2D space.
3548  * 
3549  * This method avoids building explicitly a part of \a this mesh to perform the work.
3550  *  \param [in] begin - an array of cell ids of interest.
3551  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3552  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3553  *          cells and one time. The caller is to delete this field using decrRef() as
3554  *          it is no more needed.
3555  *  \throw If the nodal connectivity of cells is not defined.
3556  *  \throw If the coordinates array is not set.
3557  *  \throw If the mesh dimension is not set.
3558  *  \throw If the mesh and space dimension is not as specified above.
3559  *  \sa buildOrthogonalField()
3560  *
3561  *  \if ENABLE_EXAMPLES
3562  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3563  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3564  *  \endif
3565  */
3566 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3567 {
3568   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3569     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3570   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3571   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3572   std::size_t nbelems=std::distance(begin,end);
3573   int nbComp=getMeshDimension()+1;
3574   array->alloc((int)nbelems,nbComp);
3575   double *vals=array->getPointer();
3576   const int *connI=_nodal_connec_index->getConstPointer();
3577   const int *conn=_nodal_connec->getConstPointer();
3578   const double *coords=_coords->getConstPointer();
3579   if(getMeshDimension()==2)
3580     {
3581       if(getSpaceDimension()==3)
3582         {
3583           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3584           const double *locPtr=loc->getConstPointer();
3585           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3586             {
3587               int offset=connI[*i];
3588               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3589               double n=INTERP_KERNEL::norm<3>(vals);
3590               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3591             }
3592         }
3593       else
3594         {
3595           for(std::size_t i=0;i<nbelems;i++)
3596             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3597         }
3598     }
3599   else//meshdimension==1
3600     {
3601       double tmp[2];
3602       for(const int *i=begin;i!=end;i++)
3603         {
3604           int offset=connI[*i];
3605           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3606           double n=INTERP_KERNEL::norm<2>(tmp);
3607           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3608           *vals++=-tmp[1];
3609           *vals++=tmp[0];
3610         }
3611     }
3612   ret->setArray(array);
3613   ret->setMesh(this);
3614   ret->synchronizeTimeWithSupport();
3615   return ret.retn();
3616 }
3617
3618 /*!
3619  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3620  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3621  * and are \b not normalized.
3622  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3623  *          cells and one time. The caller is to delete this field using decrRef() as
3624  *          it is no more needed.
3625  *  \throw If the nodal connectivity of cells is not defined.
3626  *  \throw If the coordinates array is not set.
3627  *  \throw If \a this->getMeshDimension() != 1.
3628  *  \throw If \a this mesh includes cells of type other than SEG2.
3629  */
3630 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3631 {
3632   if(getMeshDimension()!=1)
3633     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3634   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3635     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3636   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3637   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3638   int nbOfCells=getNumberOfCells();
3639   int spaceDim=getSpaceDimension();
3640   array->alloc(nbOfCells,spaceDim);
3641   double *pt=array->getPointer();
3642   const double *coo=getCoords()->getConstPointer();
3643   std::vector<int> conn;
3644   conn.reserve(2);
3645   for(int i=0;i<nbOfCells;i++)
3646     {
3647       conn.resize(0);
3648       getNodeIdsOfCell(i,conn);
3649       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3650     }
3651   ret->setArray(array);
3652   ret->setMesh(this);
3653   ret->synchronizeTimeWithSupport();
3654   return ret.retn();
3655 }
3656
3657 /*!
3658  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3659  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3660  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3661  * from. If a result face is shared by two 3D cells, then the face in included twice in
3662  * the result mesh.
3663  *  \param [in] origin - 3 components of a point defining location of the plane.
3664  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3665  *         must be greater than 1e-6.
3666  *  \param [in] eps - half-thickness of the plane.
3667  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3668  *         producing correspondent 2D cells. The caller is to delete this array
3669  *         using decrRef() as it is no more needed.
3670  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3671  *         not share the node coordinates array with \a this mesh. The caller is to
3672  *         delete this mesh using decrRef() as it is no more needed.  
3673  *  \throw If the coordinates array is not set.
3674  *  \throw If the nodal connectivity of cells is not defined.
3675  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3676  *  \throw If magnitude of \a vec is less than 1e-6.
3677  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3678  *  \throw If \a this includes quadratic cells.
3679  */
3680 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3681 {
3682   checkFullyDefined();
3683   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3684     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3685   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3686   if(candidates->empty())
3687     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3688   std::vector<int> nodes;
3689   DataArrayInt *cellIds1D=0;
3690   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3691   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3692   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3693   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3694   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3695   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3696   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3697   revDesc2=0; revDescIndx2=0;
3698   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3699   revDesc1=0; revDescIndx1=0;
3700   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3701   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3702   //
3703   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3704   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3705     cut3DCurve[*it]=-1;
3706   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3707   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3708   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3709                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3710                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3711   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3712   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3713   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3714   if(cellIds2->empty())
3715     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3716   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3717   ret->setCoords(mDesc1->getCoords());
3718   ret->setConnectivity(conn,connI,true);
3719   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3720   return ret.retn();
3721 }
3722
3723 /*!
3724  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3725 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
3726 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3727 the result mesh.
3728  *  \param [in] origin - 3 components of a point defining location of the plane.
3729  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3730  *         must be greater than 1e-6.
3731  *  \param [in] eps - half-thickness of the plane.
3732  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3733  *         producing correspondent segments. The caller is to delete this array
3734  *         using decrRef() as it is no more needed.
3735  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3736  *         mesh in 3D space. This mesh does not share the node coordinates array with
3737  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3738  *         no more needed. 
3739  *  \throw If the coordinates array is not set.
3740  *  \throw If the nodal connectivity of cells is not defined.
3741  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3742  *  \throw If magnitude of \a vec is less than 1e-6.
3743  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3744  *  \throw If \a this includes quadratic cells.
3745  */
3746 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3747 {
3748   checkFullyDefined();
3749   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3750     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3752   if(candidates->empty())
3753     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3754   std::vector<int> nodes;
3755   DataArrayInt *cellIds1D=0;
3756   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3757   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3762   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3763   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3764   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3765   //
3766   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3767   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3768     cut3DCurve[*it]=-1;
3769   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3770   int ncellsSub=subMesh->getNumberOfCells();
3771   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3772   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3773                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3774                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3775   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3776   conn->alloc(0,1);
3777   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3778   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3779   for(int i=0;i<ncellsSub;i++)
3780     {
3781       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3782         {
3783           if(cut3DSurf[i].first!=-2)
3784             {
3785               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3786               connI->pushBackSilent(conn->getNumberOfTuples());
3787               cellIds2->pushBackSilent(i);
3788             }
3789           else
3790             {
3791               int cellId3DSurf=cut3DSurf[i].second;
3792               int offset=nodalI[cellId3DSurf]+1;
3793               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3794               for(int j=0;j<nbOfEdges;j++)
3795                 {
3796                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3797                   connI->pushBackSilent(conn->getNumberOfTuples());
3798                   cellIds2->pushBackSilent(cellId3DSurf);
3799                 }
3800             }
3801         }
3802     }
3803   if(cellIds2->empty())
3804     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3805   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3806   ret->setCoords(mDesc1->getCoords());
3807   ret->setConnectivity(conn,connI,true);
3808   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3809   return ret.retn();
3810 }
3811
3812 /*!
3813  * Finds cells whose bounding boxes intersect a given plane.
3814  *  \param [in] origin - 3 components of a point defining location of the plane.
3815  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3816  *         must be greater than 1e-6.
3817  *  \param [in] eps - half-thickness of the plane.
3818  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3819  *         cells. The caller is to delete this array using decrRef() as it is no more
3820  *         needed.
3821  *  \throw If the coordinates array is not set.
3822  *  \throw If the nodal connectivity of cells is not defined.
3823  *  \throw If \a this->getSpaceDimension() != 3.
3824  *  \throw If magnitude of \a vec is less than 1e-6.
3825  *  \sa buildSlice3D()
3826  */
3827 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3828 {
3829   checkFullyDefined();
3830   if(getSpaceDimension()!=3)
3831     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3832   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3833   if(normm<1e-6)
3834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3835   double vec2[3];
3836   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3837   double angle=acos(vec[2]/normm);
3838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3839   double bbox[6];
3840   if(angle>eps)
3841     {
3842       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3843       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3844       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3845       mw->setCoords(coo);
3846       mw->getBoundingBox(bbox);
3847       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3848       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3849     }
3850   else
3851     {
3852       getBoundingBox(bbox);
3853       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3854       cellIds=getCellsInBoundingBox(bbox,eps);
3855     }
3856   return cellIds.retn();
3857 }
3858
3859 /*!
3860  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3861  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3862  * No consideration of coordinate is done by this method.
3863  * 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)
3864  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3865  */
3866 bool MEDCouplingUMesh::isContiguous1D() const
3867 {
3868   if(getMeshDimension()!=1)
3869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3870   int nbCells=getNumberOfCells();
3871   if(nbCells<1)
3872     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3873   const int *connI=_nodal_connec_index->getConstPointer();
3874   const int *conn=_nodal_connec->getConstPointer();
3875   int ref=conn[connI[0]+2];
3876   for(int i=1;i<nbCells;i++)
3877     {
3878       if(conn[connI[i]+1]!=ref)
3879         return false;
3880       ref=conn[connI[i]+2];
3881     }
3882   return true;
3883 }
3884
3885 /*!
3886  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3887  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3888  * \param pt reference point of the line
3889  * \param v normalized director vector of the line
3890  * \param eps max precision before throwing an exception
3891  * \param res output of size this->getNumberOfCells
3892  */
3893 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3894 {
3895   if(getMeshDimension()!=1)
3896     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3897   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3898     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3899   if(getSpaceDimension()!=3)
3900     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3901   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3902   const double *fPtr=f->getArray()->getConstPointer();
3903   double tmp[3];
3904   for(int i=0;i<getNumberOfCells();i++)
3905     {
3906       const double *tmp1=fPtr+3*i;
3907       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3908       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3909       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3910       double n1=INTERP_KERNEL::norm<3>(tmp);
3911       n1/=INTERP_KERNEL::norm<3>(tmp1);
3912       if(n1>eps)
3913         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3914     }
3915   const double *coo=getCoords()->getConstPointer();
3916   for(int i=0;i<getNumberOfNodes();i++)
3917     {
3918       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3919       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3920       res[i]=std::accumulate(tmp,tmp+3,0.);
3921     }
3922 }
3923
3924 /*!
3925  * 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. 
3926  * \a this is expected to be a mesh so that its space dimension is equal to its
3927  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3928  * 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).
3929  *
3930  * 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
3931  * 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).
3932  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3933  *
3934  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3935  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3936  *
3937  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3938  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3939  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3940  * \return the positive value of the distance.
3941  * \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
3942  * dimension - 1.
3943  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3944  */
3945 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3946 {
3947   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3948   if(meshDim!=spaceDim-1)
3949     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3950   if(meshDim!=2 && meshDim!=1)
3951     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3952   checkFullyDefined();
3953   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3954     { 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()); }
3955   DataArrayInt *ret1=0;
3956   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3957   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3958   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3959   cellId=*ret1Safe->begin();
3960   return *ret0->begin();
3961 }
3962
3963 /*!
3964  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3965  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3966  * 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
3967  * 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).
3968  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3969  * 
3970  * \a this is expected to be a mesh so that its space dimension is equal to its
3971  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3972  * 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).
3973  *
3974  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3975  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3976  *
3977  * \param [in] pts the list of points in which each tuple represents a point
3978  * \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.
3979  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3980  * \throw if number of components of \a pts is not equal to the space dimension.
3981  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3982  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3983  */
3984 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3985 {
3986   if(!pts)
3987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3988   pts->checkAllocated();
3989   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3990   if(meshDim!=spaceDim-1)
3991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3992   if(meshDim!=2 && meshDim!=1)
3993     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3994   if(pts->getNumberOfComponents()!=spaceDim)
3995     {
3996       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3997       throw INTERP_KERNEL::Exception(oss.str().c_str());
3998     }
3999   checkFullyDefined();
4000   int nbCells=getNumberOfCells();
4001   if(nbCells==0)
4002     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4003   int nbOfPts=pts->getNumberOfTuples();
4004   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4005   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4006   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4007   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4008   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4009   const double *bbox(bboxArr->begin());
4010   switch(spaceDim)
4011   {
4012     case 3:
4013       {
4014         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4015         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4016           {
4017             double x=std::numeric_limits<double>::max();
4018             std::vector<int> elems;
4019             myTree.getMinDistanceOfMax(ptsPtr,x);
4020             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4021             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4022           }
4023         break;
4024       }
4025     case 2:
4026       {
4027         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4028         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4029           {
4030             double x=std::numeric_limits<double>::max();
4031             std::vector<int> elems;
4032             myTree.getMinDistanceOfMax(ptsPtr,x);
4033             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4034             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4035           }
4036         break;
4037       }
4038     default:
4039       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4040   }
4041   cellIds=ret1.retn();
4042   return ret0.retn();
4043 }
4044
4045 /*!
4046  * \param [in] pt the start pointer (included) of the coordinates of the point
4047  * \param [in] cellIdsBg the start pointer (included) of cellIds
4048  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4049  * \param [in] nc nodal connectivity
4050  * \param [in] ncI nodal connectivity index
4051  * \param [in,out] ret0 the min distance between \a this and the external input point
4052  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4053  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4054  */
4055 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)
4056 {
4057   cellId=-1;
4058   ret0=std::numeric_limits<double>::max();
4059   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4060     {
4061       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4062       {
4063         case INTERP_KERNEL::NORM_TRI3:
4064           {
4065             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4066             if(tmp<ret0)
4067               { ret0=tmp; cellId=*zeCell; }
4068             break;
4069           }
4070         case INTERP_KERNEL::NORM_QUAD4:
4071         case INTERP_KERNEL::NORM_POLYGON:
4072           {
4073             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4074             if(tmp<ret0)
4075               { ret0=tmp; cellId=*zeCell; }
4076             break;
4077           }
4078         default:
4079           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4080       }
4081     }
4082 }
4083
4084 /*!
4085  * \param [in] pt the start pointer (included) of the coordinates of the point
4086  * \param [in] cellIdsBg the start pointer (included) of cellIds
4087  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4088  * \param [in] nc nodal connectivity
4089  * \param [in] ncI nodal connectivity index
4090  * \param [in,out] ret0 the min distance between \a this and the external input point
4091  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4092  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4093  */
4094 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)
4095 {
4096   cellId=-1;
4097   ret0=std::numeric_limits<double>::max();
4098   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4099     {
4100       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4101       {
4102         case INTERP_KERNEL::NORM_SEG2:
4103           {
4104             std::size_t uselessEntry=0;
4105             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4106             tmp=sqrt(tmp);
4107             if(tmp<ret0)
4108               { ret0=tmp; cellId=*zeCell; }
4109             break;
4110           }
4111         default:
4112           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4113       }
4114     }
4115 }
4116
4117 /*!
4118  * Finds cells in contact with a ball (i.e. a point with precision). 
4119  * 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.
4120  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4121  *
4122  * \warning This method is suitable if the caller intends to evaluate only one
4123  *          point, for more points getCellsContainingPoints() is recommended as it is
4124  *          faster. 
4125  *  \param [in] pos - array of coordinates of the ball central point.
4126  *  \param [in] eps - ball radius.
4127  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4128  *         if there are no such cells.
4129  *  \throw If the coordinates array is not set.
4130  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4131  */
4132 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4133 {
4134   std::vector<int> elts;
4135   getCellsContainingPoint(pos,eps,elts);
4136   if(elts.empty())
4137     return -1;
4138   return elts.front();
4139 }
4140
4141 /*!
4142  * Finds cells in contact with a ball (i.e. a point with precision).
4143  * 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.
4144  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4145  * \warning This method is suitable if the caller intends to evaluate only one
4146  *          point, for more points getCellsContainingPoints() is recommended as it is
4147  *          faster. 
4148  *  \param [in] pos - array of coordinates of the ball central point.
4149  *  \param [in] eps - ball radius.
4150  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4151  *         before inserting ids.
4152  *  \throw If the coordinates array is not set.
4153  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4154  *
4155  *  \if ENABLE_EXAMPLES
4156  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4157  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4158  *  \endif
4159  */
4160 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4161 {
4162   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4163   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4164   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4165 }
4166
4167 /// @cond INTERNAL
4168
4169 namespace ParaMEDMEM
4170 {
4171   template<const int SPACEDIMM>
4172   class DummyClsMCUG
4173   {
4174   public:
4175     static const int MY_SPACEDIM=SPACEDIMM;
4176     static const int MY_MESHDIM=8;
4177     typedef int MyConnType;
4178     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4179     // begin
4180     // useless, but for windows compilation ...
4181     const double* getCoordinatesPtr() const { return 0; }
4182     const int* getConnectivityPtr() const { return 0; }
4183     const int* getConnectivityIndexPtr() const { return 0; }
4184     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4185     // end
4186   };
4187
4188
4189
4190   /*!
4191    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4192    */
4193   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4194   {
4195     INTERP_KERNEL::Edge *ret(0);
4196     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]));
4197     m[n0]=bg[0]; m[n1]=bg[1];
4198     switch(typ)
4199     {
4200       case INTERP_KERNEL::NORM_SEG2:
4201         {
4202           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4203           break;
4204         }
4205       case INTERP_KERNEL::NORM_SEG3:
4206         {
4207           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4208           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4209           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4210           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4211           bool colinearity(inters.areColinears());
4212           delete e1; delete e2;
4213           if(colinearity)
4214             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4215           else
4216             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4217           break;
4218         }
4219       default:
4220         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4221     }
4222     return ret;
4223   }
4224
4225   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4226   {
4227     INTERP_KERNEL::Edge *ret=0;
4228     switch(typ)
4229     {
4230       case INTERP_KERNEL::NORM_SEG2:
4231         {
4232           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4233           break;
4234         }
4235       case INTERP_KERNEL::NORM_SEG3:
4236         {
4237           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4238           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4239           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4240           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4241           bool colinearity=inters.areColinears();
4242           delete e1; delete e2;
4243           if(colinearity)
4244             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4245           else
4246             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4247           mapp2[bg[2]].second=false;
4248           break;
4249         }
4250       default:
4251         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4252     }
4253     return ret;
4254   }
4255
4256   /*!
4257    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4258    * the global mesh 'mDesc'.
4259    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4260    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4261    */
4262   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4263                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4264   {
4265     mapp.clear();
4266     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.
4267     const double *coo=mDesc->getCoords()->getConstPointer();
4268     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4269     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4270     std::set<int> s;
4271     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4272       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4273     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4274       {
4275         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4276         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4277       }
4278     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4279     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4280       {
4281         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4282         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4283       }
4284     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4285       {
4286         if((*it2).second.second)
4287           mapp[(*it2).second.first]=(*it2).first;
4288         ((*it2).second.first)->decrRef();
4289       }
4290     return ret;
4291   }
4292
4293   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4294   {
4295     if(nodeId>=offset2)
4296       {
4297         int locId=nodeId-offset2;
4298         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4299       }
4300     if(nodeId>=offset1)
4301       {
4302         int locId=nodeId-offset1;
4303         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4304       }
4305     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4306   }
4307
4308   /**
4309    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4310    */
4311   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4312                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4313                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4314   {
4315     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4316       {
4317         int eltId1=abs(*desc1)-1;
4318         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4319           {
4320             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4321             if(it==mappRev.end())
4322               {
4323                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4324                 mapp[node]=*it1;
4325                 mappRev[*it1]=node;
4326               }
4327           }
4328       }
4329   }
4330 }
4331
4332 /// @endcond
4333
4334 template<int SPACEDIM>
4335 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4336                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4337 {
4338   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4339   int *eltsIndexPtr(eltsIndex->getPointer());
4340   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4341   const double *bbox(bboxArr->begin());
4342   int nbOfCells=getNumberOfCells();
4343   const int *conn=_nodal_connec->getConstPointer();
4344   const int *connI=_nodal_connec_index->getConstPointer();
4345   double bb[2*SPACEDIM];
4346   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4347   for(int i=0;i<nbOfPoints;i++)
4348     {
4349       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4350       for(int j=0;j<SPACEDIM;j++)
4351         {
4352           bb[2*j]=pos[SPACEDIM*i+j];
4353           bb[2*j+1]=pos[SPACEDIM*i+j];
4354         }
4355       std::vector<int> candidates;
4356       myTree.getIntersectingElems(bb,candidates);
4357       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4358         {
4359           int sz(connI[(*iter)+1]-connI[*iter]-1);
4360           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4361           bool status(false);
4362           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4363             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4364           else
4365             {
4366               if(SPACEDIM!=2)
4367                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4368               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4369               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4370               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4371               INTERP_KERNEL::QuadraticPolygon *pol(0);
4372               for(int j=0;j<sz;j++)
4373                 {
4374                   int nodeId(conn[connI[*iter]+1+j]);
4375                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4376                 }
4377               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4378                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4379               else
4380                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4381               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4382               double a(0.),b(0.),c(0.);
4383               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4384               status=pol->isInOrOut2(n);
4385               delete pol; n->decrRef();
4386             }
4387           if(status)
4388             {
4389               eltsIndexPtr[i+1]++;
4390               elts->pushBackSilent(*iter);
4391             }
4392         }
4393     }
4394 }
4395 /*!
4396  * Finds cells in contact with several balls (i.e. points with precision).
4397  * This method is an extension of getCellContainingPoint() and
4398  * getCellsContainingPoint() for the case of multiple points.
4399  * 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.
4400  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4401  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4402  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4403  *         this->getSpaceDimension() * \a nbOfPoints 
4404  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4405  *  \param [in] eps - radius of balls (i.e. the precision).
4406  *  \param [out] elts - vector returning ids of found cells.
4407  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4408  *         dividing cell ids in \a elts into groups each referring to one
4409  *         point. Its every element (except the last one) is an index pointing to the
4410  *         first id of a group of cells. For example cells in contact with the *i*-th
4411  *         point are described by following range of indices:
4412  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4413  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4414  *         Number of cells in contact with the *i*-th point is
4415  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4416  *  \throw If the coordinates array is not set.
4417  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4418  *
4419  *  \if ENABLE_EXAMPLES
4420  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4421  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4422  *  \endif
4423  */
4424 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4425                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4426 {
4427   int spaceDim=getSpaceDimension();
4428   int mDim=getMeshDimension();
4429   if(spaceDim==3)
4430     {
4431       if(mDim==3)
4432         {
4433           const double *coords=_coords->getConstPointer();
4434           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4435         }
4436       /*else if(mDim==2)
4437         {
4438
4439         }*/
4440       else
4441         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4442     }
4443   else if(spaceDim==2)
4444     {
4445       if(mDim==2)
4446         {
4447           const double *coords=_coords->getConstPointer();
4448           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4449         }
4450       else
4451         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4452     }
4453   else if(spaceDim==1)
4454     {
4455       if(mDim==1)
4456         {
4457           const double *coords=_coords->getConstPointer();
4458           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4459         }
4460       else
4461         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4462     }
4463   else
4464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4465 }
4466
4467 /*!
4468  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4469  * least two its edges intersect each other anywhere except their extremities. An
4470  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4471  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4472  *         cleared before filling in.
4473  *  \param [in] eps - precision.
4474  *  \throw If \a this->getMeshDimension() != 2.
4475  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4476  */
4477 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4478 {
4479   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4480   if(getMeshDimension()!=2)
4481     throw INTERP_KERNEL::Exception(msg);
4482   int spaceDim=getSpaceDimension();
4483   if(spaceDim!=2 && spaceDim!=3)
4484     throw INTERP_KERNEL::Exception(msg);
4485   const int *conn=_nodal_connec->getConstPointer();
4486   const int *connI=_nodal_connec_index->getConstPointer();
4487   int nbOfCells=getNumberOfCells();
4488   std::vector<double> cell2DinS2;
4489   for(int i=0;i<nbOfCells;i++)
4490     {
4491       int offset=connI[i];
4492       int nbOfNodesForCell=connI[i+1]-offset-1;
4493       if(nbOfNodesForCell<=3)
4494         continue;
4495       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4496       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4497       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4498         cells.push_back(i);
4499       cell2DinS2.clear();
4500     }
4501 }
4502
4503 /*!
4504  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4505  *
4506  * 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.
4507  * 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.
4508  * 
4509  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4510  * This convex envelop is computed using Jarvis march algorithm.
4511  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4512  * 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)
4513  * 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.
4514  *
4515  * \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.
4516  * \sa MEDCouplingUMesh::colinearize2D
4517  */
4518 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4519 {
4520   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4521     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4522   checkFullyDefined();
4523   const double *coords=getCoords()->getConstPointer();
4524   int nbOfCells=getNumberOfCells();
4525   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4526   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4527   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4528   int *workIndexOut=nodalConnecIndexOut->getPointer();
4529   *workIndexOut=0;
4530   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4531   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4532   std::set<INTERP_KERNEL::NormalizedCellType> types;
4533   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4534   isChanged->alloc(0,1);
4535   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4536     {
4537       int pos=nodalConnecOut->getNumberOfTuples();
4538       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4539         isChanged->pushBackSilent(i);
4540       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4541       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4542     }
4543   if(isChanged->empty())
4544     return 0;
4545   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4546   _types=types;
4547   return isChanged.retn();
4548 }
4549
4550 /*!
4551  * This method is \b NOT const because it can modify \a this.
4552  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4553  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4554  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4555  * \b 1 for translation and rotation around point of 'mesh1D'.
4556  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4557  */
4558 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4559 {
4560   checkFullyDefined();
4561   mesh1D->checkFullyDefined();
4562   if(!mesh1D->isContiguous1D())
4563     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4564   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4565     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4566   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4567     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4568   if(mesh1D->getMeshDimension()!=1)
4569     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4570   bool isQuad=false;
4571   if(isPresenceOfQuadratic())
4572     {
4573       if(mesh1D->isFullyQuadratic())
4574         isQuad=true;
4575       else
4576         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4577     }
4578   zipCoords();
4579   int oldNbOfNodes=getNumberOfNodes();
4580   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4581   switch(policy)
4582   {
4583     case 0:
4584       {
4585         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4586         break;
4587       }
4588     case 1:
4589       {
4590         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4591         break;
4592       }
4593     default:
4594       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4595   }
4596   setCoords(newCoords);
4597   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4598   updateTime();
4599   return ret.retn();
4600 }
4601
4602 /*!
4603  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4604  * If it is not the case an exception will be thrown.
4605  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4606  * intersection of plane defined by ('origin','vec').
4607  * This method has one in/out parameter : 'cut3DCurve'.
4608  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4609  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4610  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4611  * This method will throw an exception if \a this contains a non linear segment.
4612  */
4613 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4614 {
4615   checkFullyDefined();
4616   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4617     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4618   int ncells=getNumberOfCells();
4619   int nnodes=getNumberOfNodes();
4620   double vec2[3],vec3[3],vec4[3];
4621   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4622   if(normm<1e-6)
4623     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4624   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4625   const int *conn=_nodal_connec->getConstPointer();
4626   const int *connI=_nodal_connec_index->getConstPointer();
4627   const double *coo=_coords->getConstPointer();
4628   std::vector<double> addCoo;
4629   for(int i=0;i<ncells;i++)
4630     {
4631       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4632         {
4633           if(cut3DCurve[i]==-2)
4634             {
4635               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4636               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];
4637               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4638               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4639               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4640                 {
4641                   const double *st2=coo+3*st;
4642                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4643                   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]));
4644                   if(pos>eps && pos<1-eps)
4645                     {
4646                       int nNode=((int)addCoo.size())/3;
4647                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4648                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4649                       cut3DCurve[i]=nnodes+nNode;
4650                     }
4651                 }
4652             }
4653         }
4654       else
4655         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4656     }
4657   if(!addCoo.empty())
4658     {
4659       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4660       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4661       coo2->alloc(newNbOfNodes,3);
4662       double *tmp=coo2->getPointer();
4663       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4664       std::copy(addCoo.begin(),addCoo.end(),tmp);
4665       DataArrayDouble::SetArrayIn(coo2,_coords);
4666     }
4667 }
4668
4669 /*!
4670  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4671  * \param mesh1D is the input 1D mesh used for translation computation.
4672  * \return newCoords new coords filled by this method. 
4673  */
4674 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4675 {
4676   int oldNbOfNodes=getNumberOfNodes();
4677   int nbOf1DCells=mesh1D->getNumberOfCells();
4678   int spaceDim=getSpaceDimension();
4679   DataArrayDouble *ret=DataArrayDouble::New();
4680   std::vector<bool> isQuads;
4681   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4682   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4683   double *retPtr=ret->getPointer();
4684   const double *coords=getCoords()->getConstPointer();
4685   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4686   std::vector<int> v;
4687   std::vector<double> c;
4688   double vec[3];
4689   v.reserve(3);
4690   c.reserve(6);
4691   for(int i=0;i<nbOf1DCells;i++)
4692     {
4693       v.resize(0);
4694       mesh1D->getNodeIdsOfCell(i,v);
4695       c.resize(0);
4696       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4697       mesh1D->getCoordinatesOfNode(v[0],c);
4698       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4699       for(int j=0;j<oldNbOfNodes;j++)
4700         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4701       if(isQuad)
4702         {
4703           c.resize(0);
4704           mesh1D->getCoordinatesOfNode(v[1],c);
4705           mesh1D->getCoordinatesOfNode(v[0],c);
4706           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4707           for(int j=0;j<oldNbOfNodes;j++)
4708             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4709         }
4710     }
4711   ret->copyStringInfoFrom(*getCoords());
4712   return ret;
4713 }
4714
4715 /*!
4716  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4717  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4718  * \return newCoords new coords filled by this method. 
4719  */
4720 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4721 {
4722   if(mesh1D->getSpaceDimension()==2)
4723     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4724   if(mesh1D->getSpaceDimension()==3)
4725     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4726   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4727 }
4728
4729 /*!
4730  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4731  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4732  * \return newCoords new coords filled by this method. 
4733  */
4734 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4735 {
4736   if(isQuad)
4737     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4738   int oldNbOfNodes=getNumberOfNodes();
4739   int nbOf1DCells=mesh1D->getNumberOfCells();
4740   if(nbOf1DCells<2)
4741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4742   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4743   int nbOfLevsInVec=nbOf1DCells+1;
4744   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4745   double *retPtr=ret->getPointer();
4746   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4747   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4748   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4749   tmp->setCoords(tmp2);
4750   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4751   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4752   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4753   for(int i=1;i<nbOfLevsInVec;i++)
4754     {
4755       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4756       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4757       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4758       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4759       tmp->translate(vec);
4760       double tmp3[2],radius,alpha,alpha0;
4761       const double *p0=i+1<nbOfLevsInVec?begin:third;
4762       const double *p1=i+1<nbOfLevsInVec?end:begin;
4763       const double *p2=i+1<nbOfLevsInVec?third:end;
4764       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4765       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]);
4766       double angle=acos(cosangle/(radius*radius));
4767       tmp->rotate(end,0,angle);
4768       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4769     }
4770   return ret.retn();
4771 }
4772
4773 /*!
4774  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4775  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4776  * \return newCoords new coords filled by this method. 
4777  */
4778 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4779 {
4780   if(isQuad)
4781     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4782   int oldNbOfNodes=getNumberOfNodes();
4783   int nbOf1DCells=mesh1D->getNumberOfCells();
4784   if(nbOf1DCells<2)
4785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4786   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4787   int nbOfLevsInVec=nbOf1DCells+1;
4788   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4789   double *retPtr=ret->getPointer();
4790   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4791   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4792   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4793   tmp->setCoords(tmp2);
4794   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4795   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4796   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4797   for(int i=1;i<nbOfLevsInVec;i++)
4798     {
4799       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4800       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4801       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4802       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4803       tmp->translate(vec);
4804       double tmp3[2],radius,alpha,alpha0;
4805       const double *p0=i+1<nbOfLevsInVec?begin:third;
4806       const double *p1=i+1<nbOfLevsInVec?end:begin;
4807       const double *p2=i+1<nbOfLevsInVec?third:end;
4808       double vecPlane[3]={
4809         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4810         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4811         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4812       };
4813       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4814       if(norm>1.e-7)
4815         {
4816           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4817           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4818           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4819           double s2=norm2;
4820           double c2=cos(asin(s2));
4821           double m[3][3]={
4822             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4823             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4824             {-vec2[1]*s2, vec2[0]*s2, c2}
4825           };
4826           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]};
4827           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]};
4828           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]};
4829           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4830           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]);
4831           double angle=acos(cosangle/(radius*radius));
4832           tmp->rotate(end,vecPlane,angle);
4833         }
4834       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4835     }
4836   return ret.retn();
4837 }
4838
4839 /*!
4840  * This method is private because not easy to use for end user. This method is const contrary to
4841  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4842  * the coords sorted slice by slice.
4843  * \param isQuad specifies presence of quadratic cells.
4844  */
4845 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4846 {
4847   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4848   int nbOf2DCells=getNumberOfCells();
4849   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4850   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4851   const int *conn=_nodal_connec->getConstPointer();
4852   const int *connI=_nodal_connec_index->getConstPointer();
4853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4855   newConnI->alloc(nbOf3DCells+1,1);
4856   int *newConnIPtr=newConnI->getPointer();
4857   *newConnIPtr++=0;
4858   std::vector<int> newc;
4859   for(int j=0;j<nbOf2DCells;j++)
4860     {
4861       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4862       *newConnIPtr++=(int)newc.size();
4863     }
4864   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4865   int *newConnPtr=newConn->getPointer();
4866   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4867   newConnIPtr=newConnI->getPointer();
4868   for(int iz=0;iz<nbOf1DCells;iz++)
4869     {
4870       if(iz!=0)
4871         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4872       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4873         {
4874           int icell=(int)(iter-newc.begin());
4875           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4876             {
4877               if(*iter!=-1)
4878                 *newConnPtr=(*iter)+iz*deltaPerLev;
4879               else
4880                 *newConnPtr=-1;
4881             }
4882           else
4883             *newConnPtr=(*iter);
4884         }
4885     }
4886   ret->setConnectivity(newConn,newConnI,true);
4887   ret->setCoords(getCoords());
4888   return ret;
4889 }
4890
4891 /*!
4892  * Checks if \a this mesh is constituted by only quadratic cells.
4893  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4894  *  \throw If the coordinates array is not set.
4895  *  \throw If the nodal connectivity of cells is not defined.
4896  */
4897 bool MEDCouplingUMesh::isFullyQuadratic() const
4898 {
4899   checkFullyDefined();
4900   bool ret=true;
4901   int nbOfCells=getNumberOfCells();
4902   for(int i=0;i<nbOfCells && ret;i++)
4903     {
4904       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4905       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4906       ret=cm.isQuadratic();
4907     }
4908   return ret;
4909 }
4910
4911 /*!
4912  * Checks if \a this mesh includes any quadratic cell.
4913  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4914  *  \throw If the coordinates array is not set.
4915  *  \throw If the nodal connectivity of cells is not defined.
4916  */
4917 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4918 {
4919   checkFullyDefined();
4920   bool ret=false;
4921   int nbOfCells=getNumberOfCells();
4922   for(int i=0;i<nbOfCells && !ret;i++)
4923     {
4924       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4925       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4926       ret=cm.isQuadratic();
4927     }
4928   return ret;
4929 }
4930
4931 /*!
4932  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4933  * this mesh, it remains unchanged.
4934  *  \throw If the coordinates array is not set.
4935  *  \throw If the nodal connectivity of cells is not defined.
4936  */
4937 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4938 {
4939   checkFullyDefined();
4940   int nbOfCells=getNumberOfCells();
4941   int delta=0;
4942   const int *iciptr=_nodal_connec_index->getConstPointer();
4943   for(int i=0;i<nbOfCells;i++)
4944     {
4945       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4946       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4947       if(cm.isQuadratic())
4948         {
4949           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4950           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4951           if(!cml.isDynamic())
4952             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4953           else
4954             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4955         }
4956     }
4957   if(delta==0)
4958     return ;
4959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4961   const int *icptr=_nodal_connec->getConstPointer();
4962   newConn->alloc(getMeshLength()-delta,1);
4963   newConnI->alloc(nbOfCells+1,1);
4964   int *ocptr=newConn->getPointer();
4965   int *ociptr=newConnI->getPointer();
4966   *ociptr=0;
4967   _types.clear();
4968   for(int i=0;i<nbOfCells;i++,ociptr++)
4969     {
4970       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4971       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4972       if(!cm.isQuadratic())
4973         {
4974           _types.insert(type);
4975           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4976           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4977         }
4978       else
4979         {
4980           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4981           _types.insert(typel);
4982           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4983           int newNbOfNodes=cml.getNumberOfNodes();
4984           if(cml.isDynamic())
4985             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4986           *ocptr++=(int)typel;
4987           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4988           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4989         }
4990     }
4991   setConnectivity(newConn,newConnI,false);
4992 }
4993
4994 /*!
4995  * This method converts all linear cell in \a this to quadratic one.
4996  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4997  * 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)
4998  * 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.
4999  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5000  * end of the existing coordinates.
5001  * 
5002  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5003  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5004  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5005  * 
5006  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5007  *
5008  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5009  */
5010 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5011 {
5012   DataArrayInt *conn=0,*connI=0;
5013   DataArrayDouble *coords=0;
5014   std::set<INTERP_KERNEL::NormalizedCellType> types;
5015   checkFullyDefined();
5016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5017   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5018   int meshDim=getMeshDimension();
5019   switch(conversionType)
5020   {
5021     case 0:
5022       switch(meshDim)
5023       {
5024         case 1:
5025           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5026           connSafe=conn; connISafe=connI; coordsSafe=coords;
5027           break;
5028         case 2:
5029           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5030           connSafe=conn; connISafe=connI; coordsSafe=coords;
5031           break;
5032         case 3:
5033           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5034           connSafe=conn; connISafe=connI; coordsSafe=coords;
5035           break;
5036         default:
5037           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5038       }
5039       break;
5040         case 1:
5041           {
5042             switch(meshDim)
5043             {
5044               case 1:
5045                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5046                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5047                 break;
5048               case 2:
5049                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5050                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5051                 break;
5052               case 3:
5053                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5054                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5055                 break;
5056               default:
5057                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5058             }
5059             break;
5060           }
5061         default:
5062           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5063   }
5064   setConnectivity(connSafe,connISafe,false);
5065   _types=types;
5066   setCoords(coordsSafe);
5067   return ret.retn();
5068 }
5069
5070 #if 0
5071 /*!
5072  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5073  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5074  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5075  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5076  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5077  * This method can be seen as the opposite method of colinearize2D.
5078  * 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
5079  * to avoid to modify the numbering of existing nodes.
5080  *
5081  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5082  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5083  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5084  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5085  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5086  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5087  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5088  *
5089  * \sa buildDescendingConnectivity2
5090  */
5091 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5092                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5093 {
5094   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5095     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5096   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5097   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5098     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5099   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5100     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5101   //DataArrayInt *out0(0),*outi0(0);
5102   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5103   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5104   //out0s=out0s->buildUnique(); out0s->sort(true);
5105 }
5106 #endif
5107
5108 /*!
5109  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5110  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5111  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5112  */
5113 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5114 {
5115   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5116   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5117   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5118   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5119   int nbOfCells=getNumberOfCells();
5120   int nbOfNodes=getNumberOfNodes();
5121   const int *cPtr=_nodal_connec->getConstPointer();
5122   const int *icPtr=_nodal_connec_index->getConstPointer();
5123   int lastVal=0,offset=nbOfNodes;
5124   for(int i=0;i<nbOfCells;i++,icPtr++)
5125     {
5126       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5127       if(type==INTERP_KERNEL::NORM_SEG2)
5128         {
5129           types.insert(INTERP_KERNEL::NORM_SEG3);
5130           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5131           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5132           newConn->pushBackSilent(offset++);
5133           lastVal+=4;
5134           newConnI->pushBackSilent(lastVal);
5135           ret->pushBackSilent(i);
5136         }
5137       else
5138         {
5139           types.insert(type);
5140           lastVal+=(icPtr[1]-icPtr[0]);
5141           newConnI->pushBackSilent(lastVal);
5142           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5143         }
5144     }
5145   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5146   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5147   return ret.retn();
5148 }
5149
5150 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
5151 {
5152   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5153   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5154   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5155   //
5156   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5157   DataArrayInt *conn1D=0,*conn1DI=0;
5158   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5159   DataArrayDouble *coordsTmp=0;
5160   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5161   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5162   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5163   const int *c1DPtr=conn1D->begin();
5164   const int *c1DIPtr=conn1DI->begin();
5165   int nbOfCells=getNumberOfCells();
5166   const int *cPtr=_nodal_connec->getConstPointer();
5167   const int *icPtr=_nodal_connec_index->getConstPointer();
5168   int lastVal=0;
5169   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5170     {
5171       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5172       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5173       if(!cm.isQuadratic())
5174         {
5175           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5176           types.insert(typ2); newConn->pushBackSilent(typ2);
5177           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5178           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5179             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5180           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5181           newConnI->pushBackSilent(lastVal);
5182           ret->pushBackSilent(i);
5183         }
5184       else
5185         {
5186           types.insert(typ);
5187           lastVal+=(icPtr[1]-icPtr[0]);
5188           newConnI->pushBackSilent(lastVal);
5189           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5190         }
5191     }
5192   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5193   return ret.retn();
5194 }
5195
5196 /*!
5197  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5198  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5199  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5200  */
5201 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5202 {
5203   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5204   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5205   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5206 }
5207
5208 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5209 {
5210   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5211   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5212   //
5213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5214   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5215   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5216   //
5217   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5218   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5219   DataArrayInt *conn1D=0,*conn1DI=0;
5220   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5221   DataArrayDouble *coordsTmp=0;
5222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5223   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5224   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5225   const int *c1DPtr=conn1D->begin();
5226   const int *c1DIPtr=conn1DI->begin();
5227   int nbOfCells=getNumberOfCells();
5228   const int *cPtr=_nodal_connec->getConstPointer();
5229   const int *icPtr=_nodal_connec_index->getConstPointer();
5230   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5231   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5232     {
5233       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5234       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5235       if(!cm.isQuadratic())
5236         {
5237           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5238           types.insert(typ2); newConn->pushBackSilent(typ2);
5239           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5240           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5241             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5242           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5243           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5244           newConnI->pushBackSilent(lastVal);
5245           ret->pushBackSilent(i);
5246         }
5247       else
5248         {
5249           types.insert(typ);
5250           lastVal+=(icPtr[1]-icPtr[0]);
5251           newConnI->pushBackSilent(lastVal);
5252           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5253         }
5254     }
5255   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5256   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5257   return ret.retn();
5258 }
5259
5260 /*!
5261  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5262  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5263  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5264  */
5265 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5266 {
5267   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5268   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5269   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5270 }
5271
5272 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5273 {
5274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5275   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5277   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5278   //
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5282   //
5283   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5284   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5285   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5286   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5287   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5290   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5292   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5293   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5294   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5295   int nbOfCells=getNumberOfCells();
5296   const int *cPtr=_nodal_connec->getConstPointer();
5297   const int *icPtr=_nodal_connec_index->getConstPointer();
5298   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5299   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5300     {
5301       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5302       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5303       if(!cm.isQuadratic())
5304         {
5305           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5306           if(typ2==INTERP_KERNEL::NORM_ERROR)
5307             {
5308               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5309               throw INTERP_KERNEL::Exception(oss.str().c_str());
5310             }
5311           types.insert(typ2); newConn->pushBackSilent(typ2);
5312           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5313           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5314             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5315           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5316             {
5317               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5318               int tmpPos=newConn->getNumberOfTuples();
5319               newConn->pushBackSilent(nodeId2);
5320               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5321             }
5322           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5323           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5324           newConnI->pushBackSilent(lastVal);
5325           ret->pushBackSilent(i);
5326         }
5327       else
5328         {
5329           types.insert(typ);
5330           lastVal+=(icPtr[1]-icPtr[0]);
5331           newConnI->pushBackSilent(lastVal);
5332           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5333         }
5334     }
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5337   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5338   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5339   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5340   int *c=newConn->getPointer();
5341   const int *cI(newConnI->begin());
5342   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5343     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5344   offset=coordsTmp2Safe->getNumberOfTuples();
5345   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5346     c[cI[(*elt)+1]-1]+=offset;
5347   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5348   return ret.retn();
5349 }
5350
5351 /*!
5352  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5353  * so that the number of cells remains the same. Quadratic faces are converted to
5354  * polygons. This method works only for 2D meshes in
5355  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5356  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5357  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5358  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5359  *         a polylinized edge constituting the input polygon.
5360  *  \throw If the coordinates array is not set.
5361  *  \throw If the nodal connectivity of cells is not defined.
5362  *  \throw If \a this->getMeshDimension() != 2.
5363  *  \throw If \a this->getSpaceDimension() != 2.
5364  */
5365 void MEDCouplingUMesh::tessellate2D(double eps)
5366 {
5367   checkFullyDefined();
5368   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5370   double epsa=fabs(eps);
5371   if(epsa<std::numeric_limits<double>::min())
5372     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 !");
5373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5377   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5378   revDesc1=0; revDescIndx1=0;
5379   mDesc->tessellate2DCurve(eps);
5380   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5381   setCoords(mDesc->getCoords());
5382 }
5383
5384 /*!
5385  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5386  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5387  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5388  *         a sub-divided edge.
5389  *  \throw If the coordinates array is not set.
5390  *  \throw If the nodal connectivity of cells is not defined.
5391  *  \throw If \a this->getMeshDimension() != 1.
5392  *  \throw If \a this->getSpaceDimension() != 2.
5393  */
5394 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5395 {
5396   checkFullyDefined();
5397   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5398     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5399   double epsa=fabs(eps);
5400   if(epsa<std::numeric_limits<double>::min())
5401     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 !");
5402   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5403   int nbCells=getNumberOfCells();
5404   int nbNodes=getNumberOfNodes();
5405   const int *conn=_nodal_connec->getConstPointer();
5406   const int *connI=_nodal_connec_index->getConstPointer();
5407   const double *coords=_coords->getConstPointer();
5408   std::vector<double> addCoo;
5409   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5410   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5411   newConnI->alloc(nbCells+1,1);
5412   int *newConnIPtr=newConnI->getPointer();
5413   *newConnIPtr=0;
5414   int tmp1[3];
5415   INTERP_KERNEL::Node *tmp2[3];
5416   std::set<INTERP_KERNEL::NormalizedCellType> types;
5417   for(int i=0;i<nbCells;i++,newConnIPtr++)
5418     {
5419       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5420       if(cm.isQuadratic())
5421         {//assert(connI[i+1]-connI[i]-1==3)
5422           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5423           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5424           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5425           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5426           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5427           if(eac)
5428             {
5429               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5430               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5431               delete eac;
5432               newConnIPtr[1]=(int)newConn.size();
5433             }
5434           else
5435             {
5436               types.insert(INTERP_KERNEL::NORM_SEG2);
5437               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5438               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5439               newConnIPtr[1]=newConnIPtr[0]+3;
5440             }
5441         }
5442       else
5443         {
5444           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5445           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5446           newConnIPtr[1]=newConnIPtr[0]+3;
5447         }
5448     }
5449   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5450     return ;
5451   _types=types;
5452   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5454   newConnArr->alloc((int)newConn.size(),1);
5455   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5456   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5457   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5458   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5459   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5460   std::copy(addCoo.begin(),addCoo.end(),work);
5461   DataArrayDouble::SetArrayIn(newCoords,_coords);
5462   updateTime();
5463 }
5464
5465 /*!
5466  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5467  * In addition, returns an array mapping new cells to old ones. <br>
5468  * This method typically increases the number of cells in \a this mesh
5469  * but the number of nodes remains \b unchanged.
5470  * That's why the 3D splitting policies
5471  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5472  *  \param [in] policy - specifies a pattern used for splitting.
5473  * The semantic of \a policy is:
5474  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5475  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5476  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5477  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5478  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5479  *          an id of old cell producing it. The caller is to delete this array using
5480  *         decrRef() as it is no more needed. 
5481  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5482  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5483  *          and \a this->getMeshDimension() != 3. 
5484  *  \throw If \a policy is not one of the four discussed above.
5485  *  \throw If the nodal connectivity of cells is not defined.
5486  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5487  */
5488 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5489 {
5490   switch(policy)
5491   {
5492     case 0:
5493       return simplexizePol0();
5494     case 1:
5495       return simplexizePol1();
5496     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5497         return simplexizePlanarFace5();
5498     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5499         return simplexizePlanarFace6();
5500     default:
5501       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)");
5502   }
5503 }
5504
5505 /*!
5506  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5507  * - 1D: INTERP_KERNEL::NORM_SEG2
5508  * - 2D: INTERP_KERNEL::NORM_TRI3
5509  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5510  *
5511  * This method is useful for users that need to use P1 field services as
5512  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5513  * All these methods need mesh support containing only simplex cells.
5514  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5515  *  \throw If the coordinates array is not set.
5516  *  \throw If the nodal connectivity of cells is not defined.
5517  *  \throw If \a this->getMeshDimension() < 1.
5518  */
5519 bool MEDCouplingUMesh::areOnlySimplexCells() const
5520 {
5521   checkFullyDefined();
5522   int mdim=getMeshDimension();
5523   if(mdim<1 || mdim>3)
5524     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5525   int nbCells=getNumberOfCells();
5526   const int *conn=_nodal_connec->getConstPointer();
5527   const int *connI=_nodal_connec_index->getConstPointer();
5528   for(int i=0;i<nbCells;i++)
5529     {
5530       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5531       if(!cm.isSimplex())
5532         return false;
5533     }
5534   return true;
5535 }
5536
5537 /*!
5538  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5539  */
5540 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5541 {
5542   checkConnectivityFullyDefined();
5543   if(getMeshDimension()!=2)
5544     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5545   int nbOfCells=getNumberOfCells();
5546   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5547   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5548   ret->alloc(nbOfCells+nbOfCutCells,1);
5549   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5550   int *retPt=ret->getPointer();
5551   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5552   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5553   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5554   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5555   int *pt=newConn->getPointer();
5556   int *ptI=newConnI->getPointer();
5557   ptI[0]=0;
5558   const int *oldc=_nodal_connec->getConstPointer();
5559   const int *ci=_nodal_connec_index->getConstPointer();
5560   for(int i=0;i<nbOfCells;i++,ci++)
5561     {
5562       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5563         {
5564           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5565             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5566           pt=std::copy(tmp,tmp+8,pt);
5567           ptI[1]=ptI[0]+4;
5568           ptI[2]=ptI[0]+8;
5569           *retPt++=i;
5570           *retPt++=i;
5571           ptI+=2;
5572         }
5573       else
5574         {
5575           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5576           ptI[1]=ptI[0]+ci[1]-ci[0];
5577           ptI++;
5578           *retPt++=i;
5579         }
5580     }
5581   _nodal_connec->decrRef();
5582   _nodal_connec=newConn.retn();
5583   _nodal_connec_index->decrRef();
5584   _nodal_connec_index=newConnI.retn();
5585   computeTypes();
5586   updateTime();
5587   return ret.retn();
5588 }
5589
5590 /*!
5591  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5592  */
5593 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5594 {
5595   checkConnectivityFullyDefined();
5596   if(getMeshDimension()!=2)
5597     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5598   int nbOfCells=getNumberOfCells();
5599   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5600   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5601   ret->alloc(nbOfCells+nbOfCutCells,1);
5602   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5603   int *retPt=ret->getPointer();
5604   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5605   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5606   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5607   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5608   int *pt=newConn->getPointer();
5609   int *ptI=newConnI->getPointer();
5610   ptI[0]=0;
5611   const int *oldc=_nodal_connec->getConstPointer();
5612   const int *ci=_nodal_connec_index->getConstPointer();
5613   for(int i=0;i<nbOfCells;i++,ci++)
5614     {
5615       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5616         {
5617           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5618             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5619           pt=std::copy(tmp,tmp+8,pt);
5620           ptI[1]=ptI[0]+4;
5621           ptI[2]=ptI[0]+8;
5622           *retPt++=i;
5623           *retPt++=i;
5624           ptI+=2;
5625         }
5626       else
5627         {
5628           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5629           ptI[1]=ptI[0]+ci[1]-ci[0];
5630           ptI++;
5631           *retPt++=i;
5632         }
5633     }
5634   _nodal_connec->decrRef();
5635   _nodal_connec=newConn.retn();
5636   _nodal_connec_index->decrRef();
5637   _nodal_connec_index=newConnI.retn();
5638   computeTypes();
5639   updateTime();
5640   return ret.retn();
5641 }
5642
5643 /*!
5644  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5645  */
5646 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5647 {
5648   checkConnectivityFullyDefined();
5649   if(getMeshDimension()!=3)
5650     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5651   int nbOfCells=getNumberOfCells();
5652   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5653   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5654   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5655   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5656   int *retPt=ret->getPointer();
5657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5659   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5660   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5661   int *pt=newConn->getPointer();
5662   int *ptI=newConnI->getPointer();
5663   ptI[0]=0;
5664   const int *oldc=_nodal_connec->getConstPointer();
5665   const int *ci=_nodal_connec_index->getConstPointer();
5666   for(int i=0;i<nbOfCells;i++,ci++)
5667     {
5668       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5669         {
5670           for(int j=0;j<5;j++,pt+=5,ptI++)
5671             {
5672               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5673               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];
5674               *retPt++=i;
5675               ptI[1]=ptI[0]+5;
5676             }
5677         }
5678       else
5679         {
5680           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5681           ptI[1]=ptI[0]+ci[1]-ci[0];
5682           ptI++;
5683           *retPt++=i;
5684         }
5685     }
5686   _nodal_connec->decrRef();
5687   _nodal_connec=newConn.retn();
5688   _nodal_connec_index->decrRef();
5689   _nodal_connec_index=newConnI.retn();
5690   computeTypes();
5691   updateTime();
5692   return ret.retn();
5693 }
5694
5695 /*!
5696  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5697  */
5698 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5699 {
5700   checkConnectivityFullyDefined();
5701   if(getMeshDimension()!=3)
5702     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5703   int nbOfCells=getNumberOfCells();
5704   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5705   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5706   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5707   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5708   int *retPt=ret->getPointer();
5709   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5711   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5712   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5713   int *pt=newConn->getPointer();
5714   int *ptI=newConnI->getPointer();
5715   ptI[0]=0;
5716   const int *oldc=_nodal_connec->getConstPointer();
5717   const int *ci=_nodal_connec_index->getConstPointer();
5718   for(int i=0;i<nbOfCells;i++,ci++)
5719     {
5720       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5721         {
5722           for(int j=0;j<6;j++,pt+=5,ptI++)
5723             {
5724               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5725               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];
5726               *retPt++=i;
5727               ptI[1]=ptI[0]+5;
5728             }
5729         }
5730       else
5731         {
5732           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5733           ptI[1]=ptI[0]+ci[1]-ci[0];
5734           ptI++;
5735           *retPt++=i;
5736         }
5737     }
5738   _nodal_connec->decrRef();
5739   _nodal_connec=newConn.retn();
5740   _nodal_connec_index->decrRef();
5741   _nodal_connec_index=newConnI.retn();
5742   computeTypes();
5743   updateTime();
5744   return ret.retn();
5745 }
5746
5747 /*!
5748  * 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.
5749  * This method completly ignore coordinates.
5750  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5751  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5752  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5753  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5754  */
5755 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5756 {
5757   checkFullyDefined();
5758   if(getMeshDimension()!=2)
5759     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5760   int nbOfCells=getNumberOfCells();
5761   int *connI=_nodal_connec_index->getPointer();
5762   int newConnLgth=0;
5763   for(int i=0;i<nbOfCells;i++,connI++)
5764     {
5765       int offset=descIndex[i];
5766       int nbOfEdges=descIndex[i+1]-offset;
5767       //
5768       bool ddirect=desc[offset+nbOfEdges-1]>0;
5769       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5770       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5771       for(int j=0;j<nbOfEdges;j++)
5772         {
5773           bool direct=desc[offset+j]>0;
5774           int edgeId=std::abs(desc[offset+j])-1;
5775           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5776             {
5777               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5778               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5779               int ref2=direct?id1:id2;
5780               if(ref==ref2)
5781                 {
5782                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5783                   newConnLgth+=nbOfSubNodes-1;
5784                   ref=direct?id2:id1;
5785                 }
5786               else
5787                 {
5788                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5789                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5790                 }
5791             }
5792           else
5793             {
5794               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5795             }
5796         }
5797       newConnLgth++;//+1 is for cell type
5798       connI[1]=newConnLgth;
5799     }
5800   //
5801   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5802   newConn->alloc(newConnLgth,1);
5803   int *work=newConn->getPointer();
5804   for(int i=0;i<nbOfCells;i++)
5805     {
5806       *work++=INTERP_KERNEL::NORM_POLYGON;
5807       int offset=descIndex[i];
5808       int nbOfEdges=descIndex[i+1]-offset;
5809       for(int j=0;j<nbOfEdges;j++)
5810         {
5811           bool direct=desc[offset+j]>0;
5812           int edgeId=std::abs(desc[offset+j])-1;
5813           if(direct)
5814             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5815           else
5816             {
5817               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5818               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5819               work=std::copy(it,it+nbOfSubNodes-1,work);
5820             }
5821         }
5822     }
5823   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5824   _types.clear();
5825   if(nbOfCells>0)
5826     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5827 }
5828
5829 /*!
5830  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5831  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5832  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5833  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5834  * so it can be useful to call mergeNodes() before calling this method.
5835  *  \throw If \a this->getMeshDimension() <= 1.
5836  *  \throw If the coordinates array is not set.
5837  *  \throw If the nodal connectivity of cells is not defined.
5838  */
5839 void MEDCouplingUMesh::convertDegeneratedCells()
5840 {
5841   checkFullyDefined();
5842   if(getMeshDimension()<=1)
5843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5844   int nbOfCells=getNumberOfCells();
5845   if(nbOfCells<1)
5846     return ;
5847   int initMeshLgth=getMeshLength();
5848   int *conn=_nodal_connec->getPointer();
5849   int *index=_nodal_connec_index->getPointer();
5850   int posOfCurCell=0;
5851   int newPos=0;
5852   int lgthOfCurCell;
5853   for(int i=0;i<nbOfCells;i++)
5854     {
5855       lgthOfCurCell=index[i+1]-posOfCurCell;
5856       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5857       int newLgth;
5858       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5859                                                                                                      conn+newPos+1,newLgth);
5860       conn[newPos]=newType;
5861       newPos+=newLgth+1;
5862       posOfCurCell=index[i+1];
5863       index[i+1]=newPos;
5864     }
5865   if(newPos!=initMeshLgth)
5866     _nodal_connec->reAlloc(newPos);
5867   computeTypes();
5868 }
5869
5870 /*!
5871  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5872  * A cell is considered to be oriented correctly if an angle between its
5873  * normal vector and a given vector is less than \c PI / \c 2.
5874  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5875  *         cells. 
5876  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5877  *         checked.
5878  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5879  *         is not cleared before filling in.
5880  *  \throw If \a this->getMeshDimension() != 2.
5881  *  \throw If \a this->getSpaceDimension() != 3.
5882  *
5883  *  \if ENABLE_EXAMPLES
5884  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5885  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5886  *  \endif
5887  */
5888 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5889 {
5890   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5891     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5892   int nbOfCells=getNumberOfCells();
5893   const int *conn=_nodal_connec->getConstPointer();
5894   const int *connI=_nodal_connec_index->getConstPointer();
5895   const double *coordsPtr=_coords->getConstPointer();
5896   for(int i=0;i<nbOfCells;i++)
5897     {
5898       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5899       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5900         {
5901           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5902           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5903             cells.push_back(i);
5904         }
5905     }
5906 }
5907
5908 /*!
5909  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5910  * considered to be oriented correctly if an angle between its normal vector and a
5911  * given vector is less than \c PI / \c 2. 
5912  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5913  *         cells. 
5914  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5915  *         checked.
5916  *  \throw If \a this->getMeshDimension() != 2.
5917  *  \throw If \a this->getSpaceDimension() != 3.
5918  *
5919  *  \if ENABLE_EXAMPLES
5920  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5921  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5922  *  \endif
5923  */
5924 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5925 {
5926   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5927     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5928   int nbOfCells=getNumberOfCells();
5929   int *conn=_nodal_connec->getPointer();
5930   const int *connI=_nodal_connec_index->getConstPointer();
5931   const double *coordsPtr=_coords->getConstPointer();
5932   bool isModified=false;
5933   for(int i=0;i<nbOfCells;i++)
5934     {
5935       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5936       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5937         {
5938           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5939           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5940             {
5941               isModified=true;
5942               if(!isQuadratic)
5943                 {
5944                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5945                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5946                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5947                 }
5948               else
5949                 {
5950                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5951                   std::vector<int> tmp0(sz-1),tmp1(sz);
5952                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5953                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5954                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5955                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5956                 }
5957             }
5958         }
5959     }
5960   if(isModified)
5961     _nodal_connec->declareAsNew();
5962   updateTime();
5963 }
5964
5965 /*!
5966  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5967  * oriented facets. The normal vector of the facet should point out of the cell.
5968  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5969  *         is not cleared before filling in.
5970  *  \throw If \a this->getMeshDimension() != 3.
5971  *  \throw If \a this->getSpaceDimension() != 3.
5972  *  \throw If the coordinates array is not set.
5973  *  \throw If the nodal connectivity of cells is not defined.
5974  *
5975  *  \if ENABLE_EXAMPLES
5976  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5977  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5978  *  \endif
5979  */
5980 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5981 {
5982   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5983     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5984   int nbOfCells=getNumberOfCells();
5985   const int *conn=_nodal_connec->getConstPointer();
5986   const int *connI=_nodal_connec_index->getConstPointer();
5987   const double *coordsPtr=_coords->getConstPointer();
5988   for(int i=0;i<nbOfCells;i++)
5989     {
5990       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5991       if(type==INTERP_KERNEL::NORM_POLYHED)
5992         {
5993           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5994             cells.push_back(i);
5995         }
5996     }
5997 }
5998
5999 /*!
6000  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6001  * out of the cell. 
6002  *  \throw If \a this->getMeshDimension() != 3.
6003  *  \throw If \a this->getSpaceDimension() != 3.
6004  *  \throw If the coordinates array is not set.
6005  *  \throw If the nodal connectivity of cells is not defined.
6006  *  \throw If the reparation fails.
6007  *
6008  *  \if ENABLE_EXAMPLES
6009  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6010  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6011  *  \endif
6012  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6013  */
6014 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6015 {
6016   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6017     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6018   int nbOfCells=getNumberOfCells();
6019   int *conn=_nodal_connec->getPointer();
6020   const int *connI=_nodal_connec_index->getConstPointer();
6021   const double *coordsPtr=_coords->getConstPointer();
6022   for(int i=0;i<nbOfCells;i++)
6023     {
6024       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6025       if(type==INTERP_KERNEL::NORM_POLYHED)
6026         {
6027           try
6028           {
6029               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6030                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6031           }
6032           catch(INTERP_KERNEL::Exception& e)
6033           {
6034               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6035               throw INTERP_KERNEL::Exception(oss.str().c_str());
6036           }
6037         }
6038     }
6039   updateTime();
6040 }
6041
6042 /*!
6043  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6044  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6045  * according to which the first facet of the cell should be oriented to have the normal vector
6046  * pointing out of cell.
6047  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6048  *         cells. The caller is to delete this array using decrRef() as it is no more
6049  *         needed. 
6050  *  \throw If \a this->getMeshDimension() != 3.
6051  *  \throw If \a this->getSpaceDimension() != 3.
6052  *  \throw If the coordinates array is not set.
6053  *  \throw If the nodal connectivity of cells is not defined.
6054  *
6055  *  \if ENABLE_EXAMPLES
6056  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6057  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6058  *  \endif
6059  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6060  */
6061 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6062 {
6063   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6064   if(getMeshDimension()!=3)
6065     throw INTERP_KERNEL::Exception(msg);
6066   int spaceDim=getSpaceDimension();
6067   if(spaceDim!=3)
6068     throw INTERP_KERNEL::Exception(msg);
6069   //
6070   int nbOfCells=getNumberOfCells();
6071   int *conn=_nodal_connec->getPointer();
6072   const int *connI=_nodal_connec_index->getConstPointer();
6073   const double *coo=getCoords()->getConstPointer();
6074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6075   for(int i=0;i<nbOfCells;i++)
6076     {
6077       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6078       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6079         {
6080           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6081             {
6082               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6083               cells->pushBackSilent(i);
6084             }
6085         }
6086     }
6087   return cells.retn();
6088 }
6089
6090 /*!
6091  * This method is a faster method to correct orientation of all 3D cells in \a this.
6092  * 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.
6093  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6094  * 
6095  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6096  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6097  */
6098 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6099 {
6100   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6101     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6102   int nbOfCells=getNumberOfCells();
6103   int *conn=_nodal_connec->getPointer();
6104   const int *connI=_nodal_connec_index->getConstPointer();
6105   const double *coordsPtr=_coords->getConstPointer();
6106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6107   for(int i=0;i<nbOfCells;i++)
6108     {
6109       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6110       switch(type)
6111       {
6112         case INTERP_KERNEL::NORM_TETRA4:
6113           {
6114             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6115               {
6116                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6117                 ret->pushBackSilent(i);
6118               }
6119             break;
6120           }
6121         case INTERP_KERNEL::NORM_PYRA5:
6122           {
6123             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6124               {
6125                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6126                 ret->pushBackSilent(i);
6127               }
6128             break;
6129           }
6130         case INTERP_KERNEL::NORM_PENTA6:
6131         case INTERP_KERNEL::NORM_HEXA8:
6132         case INTERP_KERNEL::NORM_HEXGP12:
6133           {
6134             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6135               {
6136                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6137                 ret->pushBackSilent(i);
6138               }
6139             break;
6140           }
6141         case INTERP_KERNEL::NORM_POLYHED:
6142           {
6143             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6144               {
6145                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6146                 ret->pushBackSilent(i);
6147               }
6148             break;
6149           }
6150         default:
6151           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 !");
6152       }
6153     }
6154   updateTime();
6155   return ret.retn();
6156 }
6157
6158 /*!
6159  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6160  * If it is not the case an exception will be thrown.
6161  * This method is fast because the first cell of \a this is used to compute the plane.
6162  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6163  * \param pos output of size at least 3 used to store a point owned of searched plane.
6164  */
6165 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6166 {
6167   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6168     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6169   const int *conn=_nodal_connec->getConstPointer();
6170   const int *connI=_nodal_connec_index->getConstPointer();
6171   const double *coordsPtr=_coords->getConstPointer();
6172   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6173   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6174 }
6175
6176 /*!
6177  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6178  * cells. Currently cells of the following types are treated:
6179  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6180  * For a cell of other type an exception is thrown.
6181  * Space dimension of a 2D mesh can be either 2 or 3.
6182  * The Edge Ratio of a cell \f$t\f$ is: 
6183  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6184  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6185  *  the smallest edge lengths of \f$t\f$.
6186  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6187  *          cells and one time, lying on \a this mesh. The caller is to delete this
6188  *          field using decrRef() as it is no more needed. 
6189  *  \throw If the coordinates array is not set.
6190  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6191  *  \throw If the connectivity data array has more than one component.
6192  *  \throw If the connectivity data array has a named component.
6193  *  \throw If the connectivity index data array has more than one component.
6194  *  \throw If the connectivity index data array has a named component.
6195  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6196  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6197  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6198  */
6199 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6200 {
6201   checkCoherency();
6202   int spaceDim=getSpaceDimension();
6203   int meshDim=getMeshDimension();
6204   if(spaceDim!=2 && spaceDim!=3)
6205     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6206   if(meshDim!=2 && meshDim!=3)
6207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6208   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6209   ret->setMesh(this);
6210   int nbOfCells=getNumberOfCells();
6211   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6212   arr->alloc(nbOfCells,1);
6213   double *pt=arr->getPointer();
6214   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6215   const int *conn=_nodal_connec->getConstPointer();
6216   const int *connI=_nodal_connec_index->getConstPointer();
6217   const double *coo=_coords->getConstPointer();
6218   double tmp[12];
6219   for(int i=0;i<nbOfCells;i++,pt++)
6220     {
6221       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6222       switch(t)
6223       {
6224         case INTERP_KERNEL::NORM_TRI3:
6225           {
6226             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6227             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6228             break;
6229           }
6230         case INTERP_KERNEL::NORM_QUAD4:
6231           {
6232             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6233             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6234             break;
6235           }
6236         case INTERP_KERNEL::NORM_TETRA4:
6237           {
6238             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6239             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6240             break;
6241           }
6242         default:
6243           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6244       }
6245       conn+=connI[i+1]-connI[i];
6246     }
6247   ret->setName("EdgeRatio");
6248   ret->synchronizeTimeWithSupport();
6249   return ret.retn();
6250 }
6251
6252 /*!
6253  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6254  * cells. Currently cells of the following types are treated:
6255  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6256  * For a cell of other type an exception is thrown.
6257  * Space dimension of a 2D mesh can be either 2 or 3.
6258  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6259  *          cells and one time, lying on \a this mesh. The caller is to delete this
6260  *          field using decrRef() as it is no more needed. 
6261  *  \throw If the coordinates array is not set.
6262  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6263  *  \throw If the connectivity data array has more than one component.
6264  *  \throw If the connectivity data array has a named component.
6265  *  \throw If the connectivity index data array has more than one component.
6266  *  \throw If the connectivity index data array has a named component.
6267  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6268  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6269  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6270  */
6271 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6272 {
6273   checkCoherency();
6274   int spaceDim=getSpaceDimension();
6275   int meshDim=getMeshDimension();
6276   if(spaceDim!=2 && spaceDim!=3)
6277     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6278   if(meshDim!=2 && meshDim!=3)
6279     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6280   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6281   ret->setMesh(this);
6282   int nbOfCells=getNumberOfCells();
6283   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6284   arr->alloc(nbOfCells,1);
6285   double *pt=arr->getPointer();
6286   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6287   const int *conn=_nodal_connec->getConstPointer();
6288   const int *connI=_nodal_connec_index->getConstPointer();
6289   const double *coo=_coords->getConstPointer();
6290   double tmp[12];
6291   for(int i=0;i<nbOfCells;i++,pt++)
6292     {
6293       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6294       switch(t)
6295       {
6296         case INTERP_KERNEL::NORM_TRI3:
6297           {
6298             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6299             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6300             break;
6301           }
6302         case INTERP_KERNEL::NORM_QUAD4:
6303           {
6304             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6305             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6306             break;
6307           }
6308         case INTERP_KERNEL::NORM_TETRA4:
6309           {
6310             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6311             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6312             break;
6313           }
6314         default:
6315           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6316       }
6317       conn+=connI[i+1]-connI[i];
6318     }
6319   ret->setName("AspectRatio");
6320   ret->synchronizeTimeWithSupport();
6321   return ret.retn();
6322 }
6323
6324 /*!
6325  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6326  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6327  * treated: INTERP_KERNEL::NORM_QUAD4.
6328  * For a cell of other type an exception is thrown.
6329  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6330  *          cells and one time, lying on \a this mesh. The caller is to delete this
6331  *          field using decrRef() as it is no more needed. 
6332  *  \throw If the coordinates array is not set.
6333  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6334  *  \throw If the connectivity data array has more than one component.
6335  *  \throw If the connectivity data array has a named component.
6336  *  \throw If the connectivity index data array has more than one component.
6337  *  \throw If the connectivity index data array has a named component.
6338  *  \throw If \a this->getMeshDimension() != 2.
6339  *  \throw If \a this->getSpaceDimension() != 3.
6340  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6341  */
6342 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6343 {
6344   checkCoherency();
6345   int spaceDim=getSpaceDimension();
6346   int meshDim=getMeshDimension();
6347   if(spaceDim!=3)
6348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6349   if(meshDim!=2)
6350     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6351   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6352   ret->setMesh(this);
6353   int nbOfCells=getNumberOfCells();
6354   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6355   arr->alloc(nbOfCells,1);
6356   double *pt=arr->getPointer();
6357   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6358   const int *conn=_nodal_connec->getConstPointer();
6359   const int *connI=_nodal_connec_index->getConstPointer();
6360   const double *coo=_coords->getConstPointer();
6361   double tmp[12];
6362   for(int i=0;i<nbOfCells;i++,pt++)
6363     {
6364       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6365       switch(t)
6366       {
6367         case INTERP_KERNEL::NORM_QUAD4:
6368           {
6369             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6370             *pt=INTERP_KERNEL::quadWarp(tmp);
6371             break;
6372           }
6373         default:
6374           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6375       }
6376       conn+=connI[i+1]-connI[i];
6377     }
6378   ret->setName("Warp");
6379   ret->synchronizeTimeWithSupport();
6380   return ret.retn();
6381 }
6382
6383
6384 /*!
6385  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6386  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6387  * treated: INTERP_KERNEL::NORM_QUAD4.
6388  * For a cell of other type an exception is thrown.
6389  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6390  *          cells and one time, lying on \a this mesh. The caller is to delete this
6391  *          field using decrRef() as it is no more needed. 
6392  *  \throw If the coordinates array is not set.
6393  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6394  *  \throw If the connectivity data array has more than one component.
6395  *  \throw If the connectivity data array has a named component.
6396  *  \throw If the connectivity index data array has more than one component.
6397  *  \throw If the connectivity index data array has a named component.
6398  *  \throw If \a this->getMeshDimension() != 2.
6399  *  \throw If \a this->getSpaceDimension() != 3.
6400  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6401  */
6402 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6403 {
6404   checkCoherency();
6405   int spaceDim=getSpaceDimension();
6406   int meshDim=getMeshDimension();
6407   if(spaceDim!=3)
6408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6409   if(meshDim!=2)
6410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6411   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6412   ret->setMesh(this);
6413   int nbOfCells=getNumberOfCells();
6414   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6415   arr->alloc(nbOfCells,1);
6416   double *pt=arr->getPointer();
6417   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6418   const int *conn=_nodal_connec->getConstPointer();
6419   const int *connI=_nodal_connec_index->getConstPointer();
6420   const double *coo=_coords->getConstPointer();
6421   double tmp[12];
6422   for(int i=0;i<nbOfCells;i++,pt++)
6423     {
6424       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6425       switch(t)
6426       {
6427         case INTERP_KERNEL::NORM_QUAD4:
6428           {
6429             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6430             *pt=INTERP_KERNEL::quadSkew(tmp);
6431             break;
6432           }
6433         default:
6434           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6435       }
6436       conn+=connI[i+1]-connI[i];
6437     }
6438   ret->setName("Skew");
6439   ret->synchronizeTimeWithSupport();
6440   return ret.retn();
6441 }
6442
6443 /*!
6444  * This method aggregate the bbox of each cell and put it into bbox parameter.
6445  * 
6446  * \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)
6447  *                         For all other cases this input parameter is ignored.
6448  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6449  * 
6450  * \throw If \a this is not fully set (coordinates and connectivity).
6451  * \throw If a cell in \a this has no valid nodeId.
6452  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6453  */
6454 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6455 {
6456   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6457   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.
6458     return getBoundingBoxForBBTreeFast();
6459   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6460     {
6461       bool presenceOfQuadratic(false);
6462       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6463         {
6464           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6465           if(cm.isQuadratic())
6466             presenceOfQuadratic=true;
6467         }
6468       if(!presenceOfQuadratic)
6469         return getBoundingBoxForBBTreeFast();
6470       if(mDim==2 && sDim==2)
6471         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6472       else
6473         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6474     }
6475   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) !");
6476 }
6477
6478 /*!
6479  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6480  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6481  * 
6482  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6483  * 
6484  * \throw If \a this is not fully set (coordinates and connectivity).
6485  * \throw If a cell in \a this has no valid nodeId.
6486  */
6487 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6488 {
6489   checkFullyDefined();
6490   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6491   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6492   double *bbox(ret->getPointer());
6493   for(int i=0;i<nbOfCells*spaceDim;i++)
6494     {
6495       bbox[2*i]=std::numeric_limits<double>::max();
6496       bbox[2*i+1]=-std::numeric_limits<double>::max();
6497     }
6498   const double *coordsPtr(_coords->getConstPointer());
6499   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6500   for(int i=0;i<nbOfCells;i++)
6501     {
6502       int offset=connI[i]+1;
6503       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6504       for(int j=0;j<nbOfNodesForCell;j++)
6505         {
6506           int nodeId=conn[offset+j];
6507           if(nodeId>=0 && nodeId<nbOfNodes)
6508             {
6509               for(int k=0;k<spaceDim;k++)
6510                 {
6511                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6512                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6513                 }
6514               kk++;
6515             }
6516         }
6517       if(kk==0)
6518         {
6519           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6520           throw INTERP_KERNEL::Exception(oss.str().c_str());
6521         }
6522     }
6523   return ret.retn();
6524 }
6525
6526 /*!
6527  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6528  * useful for 2D meshes having quadratic cells
6529  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6530  * the two extremities of the arc of circle).
6531  * 
6532  * \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)
6533  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6534  * \throw If \a this is not fully defined.
6535  * \throw If \a this is not a mesh with meshDimension equal to 2.
6536  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6537  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6538  */
6539 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6540 {
6541   checkFullyDefined();
6542   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6543   if(spaceDim!=2 || mDim!=2)
6544     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!");
6545   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6546   double *bbox(ret->getPointer());
6547   const double *coords(_coords->getConstPointer());
6548   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6549   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6550     {
6551       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6552       int sz(connI[1]-connI[0]-1);
6553       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6554       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6555       INTERP_KERNEL::QuadraticPolygon *pol(0);
6556       for(int j=0;j<sz;j++)
6557         {
6558           int nodeId(conn[*connI+1+j]);
6559           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6560         }
6561       if(!cm.isQuadratic())
6562         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6563       else
6564         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6565       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6566       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6567     }
6568   return ret.retn();
6569 }
6570
6571 /*!
6572  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6573  * useful for 2D meshes having quadratic cells
6574  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6575  * the two extremities of the arc of circle).
6576  * 
6577  * \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)
6578  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6579  * \throw If \a this is not fully defined.
6580  * \throw If \a this is not a mesh with meshDimension equal to 1.
6581  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6582  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6583  */
6584 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6585 {
6586   checkFullyDefined();
6587   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6588   if(spaceDim!=2 || mDim!=1)
6589     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!");
6590   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6591   double *bbox(ret->getPointer());
6592   const double *coords(_coords->getConstPointer());
6593   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6594   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6595     {
6596       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6597       int sz(connI[1]-connI[0]-1);
6598       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6599       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6600       INTERP_KERNEL::Edge *edge(0);
6601       for(int j=0;j<sz;j++)
6602         {
6603           int nodeId(conn[*connI+1+j]);
6604           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6605         }
6606       if(!cm.isQuadratic())
6607         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6608       else
6609         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6610       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6611       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6612     }
6613   return ret.retn();
6614 }
6615
6616 /// @cond INTERNAL
6617
6618 namespace ParaMEDMEMImpl
6619 {
6620   class ConnReader
6621   {
6622   public:
6623     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6624     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6625   private:
6626     const int *_conn;
6627     int _val;
6628   };
6629
6630   class ConnReader2
6631   {
6632   public:
6633     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6634     bool operator() (const int& pos) { return _conn[pos]==_val; }
6635   private:
6636     const int *_conn;
6637     int _val;
6638   };
6639 }
6640
6641 /// @endcond
6642
6643 /*!
6644  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6645  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6646  * \a this is composed in cell types.
6647  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6648  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6649  * This parameter is kept only for compatibility with other methode listed above.
6650  */
6651 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6652 {
6653   checkConnectivityFullyDefined();
6654   const int *conn=_nodal_connec->getConstPointer();
6655   const int *connI=_nodal_connec_index->getConstPointer();
6656   const int *work=connI;
6657   int nbOfCells=getNumberOfCells();
6658   std::size_t n=getAllGeoTypes().size();
6659   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6660   std::set<INTERP_KERNEL::NormalizedCellType> types;
6661   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6662     {
6663       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6664       if(types.find(typ)!=types.end())
6665         {
6666           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6667           oss << " is not contiguous !";
6668           throw INTERP_KERNEL::Exception(oss.str().c_str());
6669         }
6670       types.insert(typ);
6671       ret[3*i]=typ;
6672       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6673       ret[3*i+1]=(int)std::distance(work,work2);
6674       work=work2;
6675     }
6676   return ret;
6677 }
6678
6679 /*!
6680  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6681  * only for types cell, type node is not managed.
6682  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6683  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6684  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6685  * If 2 or more same geometric type is in \a code and exception is thrown too.
6686  *
6687  * This method firstly checks
6688  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6689  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6690  * an exception is thrown too.
6691  * 
6692  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6693  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6694  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6695  */
6696 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6697 {
6698   if(code.empty())
6699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6700   std::size_t sz=code.size();
6701   std::size_t n=sz/3;
6702   if(sz%3!=0)
6703     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6704   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6705   int nb=0;
6706   bool isNoPflUsed=true;
6707   for(std::size_t i=0;i<n;i++)
6708     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6709       {
6710         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6711         nb+=code[3*i+1];
6712         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6713           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6714         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6715       }
6716   if(types.size()!=n)
6717     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6718   if(isNoPflUsed)
6719     {
6720       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6721         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6722       if(types.size()==_types.size())
6723         return 0;
6724     }
6725   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6726   ret->alloc(nb,1);
6727   int *retPtr=ret->getPointer();
6728   const int *connI=_nodal_connec_index->getConstPointer();
6729   const int *conn=_nodal_connec->getConstPointer();
6730   int nbOfCells=getNumberOfCells();
6731   const int *i=connI;
6732   int kk=0;
6733   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6734     {
6735       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6736       int offset=(int)std::distance(connI,i);
6737       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6738       int nbOfCellsOfCurType=(int)std::distance(i,j);
6739       if(code[3*kk+2]==-1)
6740         for(int k=0;k<nbOfCellsOfCurType;k++)
6741           *retPtr++=k+offset;
6742       else
6743         {
6744           int idInIdsPerType=code[3*kk+2];
6745           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6746             {
6747               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6748               if(zePfl)
6749                 {
6750                   zePfl->checkAllocated();
6751                   if(zePfl->getNumberOfComponents()==1)
6752                     {
6753                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6754                         {
6755                           if(*k>=0 && *k<nbOfCellsOfCurType)
6756                             *retPtr=(*k)+offset;
6757                           else
6758                             {
6759                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6760                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6761                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6762                             }
6763                         }
6764                     }
6765                   else
6766                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6767                 }
6768               else
6769                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6770             }
6771           else
6772             {
6773               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6774               oss << " should be in [0," << idsPerType.size() << ") !";
6775               throw INTERP_KERNEL::Exception(oss.str().c_str());
6776             }
6777         }
6778       i=j;
6779     }
6780   return ret.retn();
6781 }
6782
6783 /*!
6784  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6785  * 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.
6786  * 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.
6787  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6788  * 
6789  * \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.
6790  * \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,
6791  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6792  * \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.
6793  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6794  * \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
6795  */
6796 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6797 {
6798   if(!profile)
6799     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6800   if(profile->getNumberOfComponents()!=1)
6801     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6802   checkConnectivityFullyDefined();
6803   const int *conn=_nodal_connec->getConstPointer();
6804   const int *connI=_nodal_connec_index->getConstPointer();
6805   int nbOfCells=getNumberOfCells();
6806   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6807   std::vector<int> typeRangeVals(1);
6808   for(const int *i=connI;i!=connI+nbOfCells;)
6809     {
6810       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6811       if(std::find(types.begin(),types.end(),curType)!=types.end())
6812         {
6813           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6814         }
6815       types.push_back(curType);
6816       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6817       typeRangeVals.push_back((int)std::distance(connI,i));
6818     }
6819   //
6820   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6821   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6824   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6825   //
6826   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6827   code.resize(3*nbOfCastsFinal);
6828   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6829   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6830   for(int i=0;i<nbOfCastsFinal;i++)
6831     {
6832       int castId=castsPresent->getIJ(i,0);
6833       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6834       idsInPflPerType2.push_back(tmp3);
6835       code[3*i]=(int)types[castId];
6836       code[3*i+1]=tmp3->getNumberOfTuples();
6837       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6838       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6839         {
6840           tmp4->copyStringInfoFrom(*profile);
6841           idsPerType2.push_back(tmp4);
6842           code[3*i+2]=(int)idsPerType2.size()-1;
6843         }
6844       else
6845         {
6846           code[3*i+2]=-1;
6847         }
6848     }
6849   std::size_t sz2=idsInPflPerType2.size();
6850   idsInPflPerType.resize(sz2);
6851   for(std::size_t i=0;i<sz2;i++)
6852     {
6853       DataArrayInt *locDa=idsInPflPerType2[i];
6854       locDa->incrRef();
6855       idsInPflPerType[i]=locDa;
6856     }
6857   std::size_t sz=idsPerType2.size();
6858   idsPerType.resize(sz);
6859   for(std::size_t i=0;i<sz;i++)
6860     {
6861       DataArrayInt *locDa=idsPerType2[i];
6862       locDa->incrRef();
6863       idsPerType[i]=locDa;
6864     }
6865 }
6866
6867 /*!
6868  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6869  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6870  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6871  * 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.
6872  */
6873 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6874 {
6875   checkFullyDefined();
6876   nM1LevMesh->checkFullyDefined();
6877   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6878     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6879   if(_coords!=nM1LevMesh->getCoords())
6880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6881   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6883   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6885   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6886   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6887   tmp->setConnectivity(tmp0,tmp1);
6888   tmp->renumberCells(ret0->getConstPointer(),false);
6889   revDesc=tmp->getNodalConnectivity();
6890   revDescIndx=tmp->getNodalConnectivityIndex();
6891   DataArrayInt *ret=0;
6892   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6893     {
6894       int tmp2;
6895       ret->getMaxValue(tmp2);
6896       ret->decrRef();
6897       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6898       throw INTERP_KERNEL::Exception(oss.str().c_str());
6899     }
6900   nM1LevMeshIds=ret;
6901   //
6902   revDesc->incrRef();
6903   revDescIndx->incrRef();
6904   ret1->incrRef();
6905   ret0->incrRef();
6906   meshnM1Old2New=ret0;
6907   return ret1;
6908 }
6909
6910 /*!
6911  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6912  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6913  * in "Old to New" mode.
6914  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6915  *          this array using decrRef() as it is no more needed.
6916  *  \throw If the nodal connectivity of cells is not defined.
6917  */
6918 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6919 {
6920   checkConnectivityFullyDefined();
6921   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6922   renumberCells(ret->getConstPointer(),false);
6923   return ret.retn();
6924 }
6925
6926 /*!
6927  * This methods checks that cells are sorted by their types.
6928  * This method makes asumption (no check) that connectivity is correctly set before calling.
6929  */
6930 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6931 {
6932   checkFullyDefined();
6933   const int *conn=_nodal_connec->getConstPointer();
6934   const int *connI=_nodal_connec_index->getConstPointer();
6935   int nbOfCells=getNumberOfCells();
6936   std::set<INTERP_KERNEL::NormalizedCellType> types;
6937   for(const int *i=connI;i!=connI+nbOfCells;)
6938     {
6939       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6940       if(types.find(curType)!=types.end())
6941         return false;
6942       types.insert(curType);
6943       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6944     }
6945   return true;
6946 }
6947
6948 /*!
6949  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6950  * The geometric type order is specified by MED file.
6951  * 
6952  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6953  */
6954 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6955 {
6956   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6957 }
6958
6959 /*!
6960  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6961  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6962  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6963  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6964  */
6965 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6966 {
6967   checkFullyDefined();
6968   const int *conn=_nodal_connec->getConstPointer();
6969   const int *connI=_nodal_connec_index->getConstPointer();
6970   int nbOfCells=getNumberOfCells();
6971   if(nbOfCells==0)
6972     return true;
6973   int lastPos=-1;
6974   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6975   for(const int *i=connI;i!=connI+nbOfCells;)
6976     {
6977       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6978       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6979       if(isTypeExists!=orderEnd)
6980         {
6981           int pos=(int)std::distance(orderBg,isTypeExists);
6982           if(pos<=lastPos)
6983             return false;
6984           lastPos=pos;
6985           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6986         }
6987       else
6988         {
6989           if(sg.find(curType)==sg.end())
6990             {
6991               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6992               sg.insert(curType);
6993             }
6994           else
6995             return false;
6996         }
6997     }
6998   return true;
6999 }
7000
7001 /*!
7002  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7003  * 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
7004  * 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'.
7005  */
7006 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7007 {
7008   checkConnectivityFullyDefined();
7009   int nbOfCells=getNumberOfCells();
7010   const int *conn=_nodal_connec->getConstPointer();
7011   const int *connI=_nodal_connec_index->getConstPointer();
7012   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7013   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7014   tmpa->alloc(nbOfCells,1);
7015   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7016   tmpb->fillWithZero();
7017   int *tmp=tmpa->getPointer();
7018   int *tmp2=tmpb->getPointer();
7019   for(const int *i=connI;i!=connI+nbOfCells;i++)
7020     {
7021       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7022       if(where!=orderEnd)
7023         {
7024           int pos=(int)std::distance(orderBg,where);
7025           tmp2[pos]++;
7026           tmp[std::distance(connI,i)]=pos;
7027         }
7028       else
7029         {
7030           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7031           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7032           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7033           throw INTERP_KERNEL::Exception(oss.str().c_str());
7034         }
7035     }
7036   nbPerType=tmpb.retn();
7037   return tmpa.retn();
7038 }
7039
7040 /*!
7041  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7042  *
7043  * \return a new object containing the old to new correspondance.
7044  *
7045  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7046  */
7047 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7048 {
7049   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7050 }
7051
7052 /*!
7053  * 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.
7054  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7055  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7056  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7057  */
7058 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7059 {
7060   DataArrayInt *nbPerType=0;
7061   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7062   nbPerType->decrRef();
7063   return tmpa->buildPermArrPerLevel();
7064 }
7065
7066 /*!
7067  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7068  * The number of cells remains unchanged after the call of this method.
7069  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7070  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7071  *
7072  * \return the array giving the correspondance old to new.
7073  */
7074 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7075 {
7076   checkFullyDefined();
7077   computeTypes();
7078   const int *conn=_nodal_connec->getConstPointer();
7079   const int *connI=_nodal_connec_index->getConstPointer();
7080   int nbOfCells=getNumberOfCells();
7081   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7082   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7083     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7084       {
7085         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7086         types.push_back(curType);
7087         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7088       }
7089   DataArrayInt *ret=DataArrayInt::New();
7090   ret->alloc(nbOfCells,1);
7091   int *retPtr=ret->getPointer();
7092   std::fill(retPtr,retPtr+nbOfCells,-1);
7093   int newCellId=0;
7094   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7095     {
7096       for(const int *i=connI;i!=connI+nbOfCells;i++)
7097         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7098           retPtr[std::distance(connI,i)]=newCellId++;
7099     }
7100   renumberCells(retPtr,false);
7101   return ret;
7102 }
7103
7104 /*!
7105  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7106  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7107  * This method makes asumption that connectivity is correctly set before calling.
7108  */
7109 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7110 {
7111   checkConnectivityFullyDefined();
7112   const int *conn=_nodal_connec->getConstPointer();
7113   const int *connI=_nodal_connec_index->getConstPointer();
7114   int nbOfCells=getNumberOfCells();
7115   std::vector<MEDCouplingUMesh *> ret;
7116   for(const int *i=connI;i!=connI+nbOfCells;)
7117     {
7118       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7119       int beginCellId=(int)std::distance(connI,i);
7120       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7121       int endCellId=(int)std::distance(connI,i);
7122       int sz=endCellId-beginCellId;
7123       int *cells=new int[sz];
7124       for(int j=0;j<sz;j++)
7125         cells[j]=beginCellId+j;
7126       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7127       delete [] cells;
7128       ret.push_back(m);
7129     }
7130   return ret;
7131 }
7132
7133 /*!
7134  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7135  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7136  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7137  *
7138  * \return a newly allocated instance, that the caller must manage.
7139  * \throw If \a this contains more than one geometric type.
7140  * \throw If the nodal connectivity of \a this is not fully defined.
7141  * \throw If the internal data is not coherent.
7142  */
7143 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7144 {
7145   checkConnectivityFullyDefined();
7146   if(_types.size()!=1)
7147     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7148   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7149   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7150   ret->setCoords(getCoords());
7151   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7152   if(retC)
7153     {
7154       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7155       retC->setNodalConnectivity(c);
7156     }
7157   else
7158     {
7159       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7160       if(!retD)
7161         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7162       DataArrayInt *c=0,*ci=0;
7163       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7164       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7165       retD->setNodalConnectivity(cs,cis);
7166     }
7167   return ret.retn();
7168 }
7169
7170 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7171 {
7172   checkConnectivityFullyDefined();
7173   if(_types.size()!=1)
7174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7175   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7176   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7177   if(cm.isDynamic())
7178     {
7179       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7180       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7181       throw INTERP_KERNEL::Exception(oss.str().c_str());
7182     }
7183   int nbCells=getNumberOfCells();
7184   int typi=(int)typ;
7185   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7186   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7187   int *outPtr=connOut->getPointer();
7188   const int *conn=_nodal_connec->begin();
7189   const int *connI=_nodal_connec_index->begin();
7190   nbNodesPerCell++;
7191   for(int i=0;i<nbCells;i++,connI++)
7192     {
7193       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7194         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7195       else
7196         {
7197           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 << ") !";
7198           throw INTERP_KERNEL::Exception(oss.str().c_str());
7199         }
7200     }
7201   return connOut.retn();
7202 }
7203
7204 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7205 {
7206   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7207   checkConnectivityFullyDefined();
7208   if(_types.size()!=1)
7209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7210   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7211   if(lgth<nbCells)
7212     throw INTERP_KERNEL::Exception(msg0);
7213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7214   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7215   int *cp(c->getPointer()),*cip(ci->getPointer());
7216   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7217   cip[0]=0;
7218   for(int i=0;i<nbCells;i++,cip++,incip++)
7219     {
7220       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7221       int delta(stop-strt);
7222       if(delta>=1)
7223         {
7224           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7225             cp=std::copy(incp+strt,incp+stop,cp);
7226           else
7227             throw INTERP_KERNEL::Exception(msg0);
7228         }
7229       else
7230         throw INTERP_KERNEL::Exception(msg0);
7231       cip[1]=cip[0]+delta;
7232     }
7233   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7234 }
7235
7236 /*!
7237  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7238  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7239  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7240  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7241  * are not used here to avoid the build of big permutation array.
7242  *
7243  * \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
7244  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7245  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7246  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7247  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7248  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7249  * \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
7250  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7251  */
7252 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7253                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7254                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7255 {
7256   std::vector<const MEDCouplingUMesh *> ms2;
7257   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7258     if(*it)
7259       {
7260         (*it)->checkConnectivityFullyDefined();
7261         ms2.push_back(*it);
7262       }
7263   if(ms2.empty())
7264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7265   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7266   int meshDim=ms2[0]->getMeshDimension();
7267   std::vector<const MEDCouplingUMesh *> m1ssm;
7268   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7269   //
7270   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7271   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7272   int fake=0,rk=0;
7273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7274   ret1->alloc(0,1); ret2->alloc(0,1);
7275   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7276     {
7277       if(meshDim!=(*it)->getMeshDimension())
7278         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7279       if(refCoo!=(*it)->getCoords())
7280         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7281       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7282       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7283       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7284       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7285         {
7286           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7287           m1ssmSingleAuto.push_back(singleCell);
7288           m1ssmSingle.push_back(singleCell);
7289           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7290         }
7291     }
7292   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7293   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7294   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7295   for(std::size_t i=0;i<m1ssm.size();i++)
7296     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7297   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7298   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7299   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7300   return ret0.retn();
7301 }
7302
7303 /*!
7304  * This method returns a newly created DataArrayInt instance.
7305  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7306  */
7307 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7308 {
7309   checkFullyDefined();
7310   const int *conn=_nodal_connec->getConstPointer();
7311   const int *connIndex=_nodal_connec_index->getConstPointer();
7312   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7313   for(const int *w=begin;w!=end;w++)
7314     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7315       ret->pushBackSilent(*w);
7316   return ret.retn();
7317 }
7318
7319 /*!
7320  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7321  * are in [0:getNumberOfCells())
7322  */
7323 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7324 {
7325   checkFullyDefined();
7326   const int *conn=_nodal_connec->getConstPointer();
7327   const int *connI=_nodal_connec_index->getConstPointer();
7328   int nbOfCells=getNumberOfCells();
7329   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7330   int *tmp=new int[nbOfCells];
7331   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7332     {
7333       int j=0;
7334       for(const int *i=connI;i!=connI+nbOfCells;i++)
7335         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7336           tmp[std::distance(connI,i)]=j++;
7337     }
7338   DataArrayInt *ret=DataArrayInt::New();
7339   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7340   ret->copyStringInfoFrom(*da);
7341   int *retPtr=ret->getPointer();
7342   const int *daPtr=da->getConstPointer();
7343   int nbOfElems=da->getNbOfElems();
7344   for(int k=0;k<nbOfElems;k++)
7345     retPtr[k]=tmp[daPtr[k]];
7346   delete [] tmp;
7347   return ret;
7348 }
7349
7350 /*!
7351  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7352  * This method \b works \b for mesh sorted by type.
7353  * cells whose ids is in 'idsPerGeoType' array.
7354  * This method conserves coords and name of mesh.
7355  */
7356 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7357 {
7358   std::vector<int> code=getDistributionOfTypes();
7359   std::size_t nOfTypesInThis=code.size()/3;
7360   int sz=0,szOfType=0;
7361   for(std::size_t i=0;i<nOfTypesInThis;i++)
7362     {
7363       if(code[3*i]!=type)
7364         sz+=code[3*i+1];
7365       else
7366         szOfType=code[3*i+1];
7367     }
7368   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7369     if(*work<0 || *work>=szOfType)
7370       {
7371         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7372         oss << ". It should be in [0," << szOfType << ") !";
7373         throw INTERP_KERNEL::Exception(oss.str().c_str());
7374       }
7375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7376   int *idsPtr=idsTokeep->getPointer();
7377   int offset=0;
7378   for(std::size_t i=0;i<nOfTypesInThis;i++)
7379     {
7380       if(code[3*i]!=type)
7381         for(int j=0;j<code[3*i+1];j++)
7382           *idsPtr++=offset+j;
7383       else
7384         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7385       offset+=code[3*i+1];
7386     }
7387   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7388   ret->copyTinyInfoFrom(this);
7389   return ret.retn();
7390 }
7391
7392 /*!
7393  * This method returns a vector of size 'this->getNumberOfCells()'.
7394  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7395  */
7396 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7397 {
7398   int ncell=getNumberOfCells();
7399   std::vector<bool> ret(ncell);
7400   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7401   const int *c=getNodalConnectivity()->getConstPointer();
7402   for(int i=0;i<ncell;i++)
7403     {
7404       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7405       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7406       ret[i]=cm.isQuadratic();
7407     }
7408   return ret;
7409 }
7410
7411 /*!
7412  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7413  */
7414 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7415 {
7416   if(other->getType()!=UNSTRUCTURED)
7417     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7418   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7419   return MergeUMeshes(this,otherC);
7420 }
7421
7422 /*!
7423  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7424  * computed by averaging coordinates of cell nodes, so this method is not a right
7425  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7426  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7427  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7428  *          components. The caller is to delete this array using decrRef() as it is
7429  *          no more needed.
7430  *  \throw If the coordinates array is not set.
7431  *  \throw If the nodal connectivity of cells is not defined.
7432  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7433  */
7434 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7435 {
7436   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7437   int spaceDim=getSpaceDimension();
7438   int nbOfCells=getNumberOfCells();
7439   ret->alloc(nbOfCells,spaceDim);
7440   ret->copyStringInfoFrom(*getCoords());
7441   double *ptToFill=ret->getPointer();
7442   const int *nodal=_nodal_connec->getConstPointer();
7443   const int *nodalI=_nodal_connec_index->getConstPointer();
7444   const double *coor=_coords->getConstPointer();
7445   for(int i=0;i<nbOfCells;i++)
7446     {
7447       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7448       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7449       ptToFill+=spaceDim;
7450     }
7451   return ret.retn();
7452 }
7453
7454 /*!
7455  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7456  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7457  * 
7458  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7459  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7460  * 
7461  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7462  * \throw If \a this is not fully defined (coordinates and connectivity)
7463  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7464  */
7465 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7466 {
7467   checkFullyDefined();
7468   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7469   int spaceDim=getSpaceDimension();
7470   int nbOfCells=getNumberOfCells();
7471   int nbOfNodes=getNumberOfNodes();
7472   ret->alloc(nbOfCells,spaceDim);
7473   double *ptToFill=ret->getPointer();
7474   const int *nodal=_nodal_connec->getConstPointer();
7475   const int *nodalI=_nodal_connec_index->getConstPointer();
7476   const double *coor=_coords->getConstPointer();
7477   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7478     {
7479       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7480       std::fill(ptToFill,ptToFill+spaceDim,0.);
7481       if(type!=INTERP_KERNEL::NORM_POLYHED)
7482         {
7483           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7484             {
7485               if(*conn>=0 && *conn<nbOfNodes)
7486                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7487               else
7488                 {
7489                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7490                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7491                 }
7492             }
7493           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7494           if(nbOfNodesInCell>0)
7495             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7496           else
7497             {
7498               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7499               throw INTERP_KERNEL::Exception(oss.str().c_str());
7500             }
7501         }
7502       else
7503         {
7504           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7505           s.erase(-1);
7506           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7507             {
7508               if(*it>=0 && *it<nbOfNodes)
7509                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7510               else
7511                 {
7512                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7513                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7514                 }
7515             }
7516           if(!s.empty())
7517             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7518           else
7519             {
7520               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7521               throw INTERP_KERNEL::Exception(oss.str().c_str());
7522             }
7523         }
7524     }
7525   return ret.retn();
7526 }
7527
7528 /*!
7529  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7530  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7531  * are specified via an array of cell ids. 
7532  *  \warning Validity of the specified cell ids is not checked! 
7533  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7534  *  \param [in] begin - an array of cell ids of interest.
7535  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7536  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7537  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7538  *          caller is to delete this array using decrRef() as it is no more needed. 
7539  *  \throw If the coordinates array is not set.
7540  *  \throw If the nodal connectivity of cells is not defined.
7541  *
7542  *  \if ENABLE_EXAMPLES
7543  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7544  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7545  *  \endif
7546  */
7547 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7548 {
7549   DataArrayDouble *ret=DataArrayDouble::New();
7550   int spaceDim=getSpaceDimension();
7551   int nbOfTuple=(int)std::distance(begin,end);
7552   ret->alloc(nbOfTuple,spaceDim);
7553   double *ptToFill=ret->getPointer();
7554   double *tmp=new double[spaceDim];
7555   const int *nodal=_nodal_connec->getConstPointer();
7556   const int *nodalI=_nodal_connec_index->getConstPointer();
7557   const double *coor=_coords->getConstPointer();
7558   for(const int *w=begin;w!=end;w++)
7559     {
7560       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7561       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7562       ptToFill+=spaceDim;
7563     }
7564   delete [] tmp;
7565   return ret;
7566 }
7567
7568 /*!
7569  * 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".
7570  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7571  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7572  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7573  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7574  * 
7575  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7576  * \throw If spaceDim!=3 or meshDim!=2.
7577  * \throw If connectivity of \a this is invalid.
7578  * \throw If connectivity of a cell in \a this points to an invalid node.
7579  */
7580 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7581 {
7582   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7583   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7584   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7585     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7586   ret->alloc(nbOfCells,4);
7587   double *retPtr(ret->getPointer());
7588   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7589   const double *coor(_coords->begin());
7590   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7591     {
7592       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7593       if(nodalI[1]-nodalI[0]>=3)
7594         {
7595           for(int j=0;j<3;j++)
7596             {
7597               int nodeId(nodal[nodalI[0]+1+j]);
7598               if(nodeId>=0 && nodeId<nbOfNodes)
7599                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7600               else
7601                 {
7602                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7603                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7604                 }
7605             }
7606         }
7607       else
7608         {
7609           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7610           throw INTERP_KERNEL::Exception(oss.str().c_str());
7611         }
7612       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7613       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7614     }
7615   return ret.retn();
7616 }
7617
7618 /*!
7619  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7620  * 
7621  */
7622 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7623 {
7624   if(!da)
7625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7626   da->checkAllocated();
7627   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7628   ret->setCoords(da);
7629   int nbOfTuples=da->getNumberOfTuples();
7630   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7632   c->alloc(2*nbOfTuples,1);
7633   cI->alloc(nbOfTuples+1,1);
7634   int *cp=c->getPointer();
7635   int *cip=cI->getPointer();
7636   *cip++=0;
7637   for(int i=0;i<nbOfTuples;i++)
7638     {
7639       *cp++=INTERP_KERNEL::NORM_POINT1;
7640       *cp++=i;
7641       *cip++=2*(i+1);
7642     }
7643   ret->setConnectivity(c,cI,true);
7644   return ret.retn();
7645 }
7646 /*!
7647  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7648  * Cells and nodes of
7649  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7650  *  \param [in] mesh1 - the first mesh.
7651  *  \param [in] mesh2 - the second mesh.
7652  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7653  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7654  *          is no more needed.
7655  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7656  *  \throw If the coordinates array is not set in none of the meshes.
7657  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7658  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7659  */
7660 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7661 {
7662   std::vector<const MEDCouplingUMesh *> tmp(2);
7663   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7664   return MergeUMeshes(tmp);
7665 }
7666
7667 /*!
7668  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7669  * Cells and nodes of
7670  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7671  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7672  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7673  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7674  *          is no more needed.
7675  *  \throw If \a a.size() == 0.
7676  *  \throw If \a a[ *i* ] == NULL.
7677  *  \throw If the coordinates array is not set in none of the meshes.
7678  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7679  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7680  */
7681 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7682 {
7683   std::size_t sz=a.size();
7684   if(sz==0)
7685     return MergeUMeshesLL(a);
7686   for(std::size_t ii=0;ii<sz;ii++)
7687     if(!a[ii])
7688       {
7689         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7690         throw INTERP_KERNEL::Exception(oss.str().c_str());
7691       }
7692   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7693   std::vector< const MEDCouplingUMesh * > aa(sz);
7694   int spaceDim=-3;
7695   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7696     {
7697       const MEDCouplingUMesh *cur=a[i];
7698       const DataArrayDouble *coo=cur->getCoords();
7699       if(coo)
7700         spaceDim=coo->getNumberOfComponents();
7701     }
7702   if(spaceDim==-3)
7703     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7704   for(std::size_t i=0;i<sz;i++)
7705     {
7706       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7707       aa[i]=bb[i];
7708     }
7709   return MergeUMeshesLL(aa);
7710 }
7711
7712 /// @cond INTERNAL
7713
7714 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7715 {
7716   if(a.empty())
7717     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7718   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7719   int meshDim=(*it)->getMeshDimension();
7720   int nbOfCells=(*it)->getNumberOfCells();
7721   int meshLgth=(*it++)->getMeshLength();
7722   for(;it!=a.end();it++)
7723     {
7724       if(meshDim!=(*it)->getMeshDimension())
7725         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7726       nbOfCells+=(*it)->getNumberOfCells();
7727       meshLgth+=(*it)->getMeshLength();
7728     }
7729   std::vector<const MEDCouplingPointSet *> aps(a.size());
7730   std::copy(a.begin(),a.end(),aps.begin());
7731   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7732   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7733   ret->setCoords(pts);
7734   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7735   c->alloc(meshLgth,1);
7736   int *cPtr=c->getPointer();
7737   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7738   cI->alloc(nbOfCells+1,1);
7739   int *cIPtr=cI->getPointer();
7740   *cIPtr++=0;
7741   int offset=0;
7742   int offset2=0;
7743   for(it=a.begin();it!=a.end();it++)
7744     {
7745       int curNbOfCell=(*it)->getNumberOfCells();
7746       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7747       const int *curC=(*it)->_nodal_connec->getConstPointer();
7748       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7749       for(int j=0;j<curNbOfCell;j++)
7750         {
7751           const int *src=curC+curCI[j];
7752           *cPtr++=*src++;
7753           for(;src!=curC+curCI[j+1];src++,cPtr++)
7754             {
7755               if(*src!=-1)
7756                 *cPtr=*src+offset2;
7757               else
7758                 *cPtr=-1;
7759             }
7760         }
7761       offset+=curCI[curNbOfCell];
7762       offset2+=(*it)->getNumberOfNodes();
7763     }
7764   //
7765   ret->setConnectivity(c,cI,true);
7766   return ret.retn();
7767 }
7768
7769 /// @endcond
7770
7771 /*!
7772  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7773  * dimension and sharing the node coordinates array.
7774  * All cells of the first mesh precede all cells of the second mesh
7775  * within the result mesh. 
7776  *  \param [in] mesh1 - the first mesh.
7777  *  \param [in] mesh2 - the second mesh.
7778  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7779  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7780  *          is no more needed.
7781  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7782  *  \throw If the meshes do not share the node coordinates array.
7783  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7784  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7785  */
7786 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7787 {
7788   std::vector<const MEDCouplingUMesh *> tmp(2);
7789   tmp[0]=mesh1; tmp[1]=mesh2;
7790   return MergeUMeshesOnSameCoords(tmp);
7791 }
7792
7793 /*!
7794  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7795  * dimension and sharing the node coordinates array.
7796  * All cells of the *i*-th mesh precede all cells of the
7797  * (*i*+1)-th mesh within the result mesh.
7798  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7799  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7800  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7801  *          is no more needed.
7802  *  \throw If \a a.size() == 0.
7803  *  \throw If \a a[ *i* ] == NULL.
7804  *  \throw If the meshes do not share the node coordinates array.
7805  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7806  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7807  */
7808 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7809 {
7810   if(meshes.empty())
7811     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7812   for(std::size_t ii=0;ii<meshes.size();ii++)
7813     if(!meshes[ii])
7814       {
7815         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7816         throw INTERP_KERNEL::Exception(oss.str().c_str());
7817       }
7818   const DataArrayDouble *coords=meshes.front()->getCoords();
7819   int meshDim=meshes.front()->getMeshDimension();
7820   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7821   int meshLgth=0;
7822   int meshIndexLgth=0;
7823   for(;iter!=meshes.end();iter++)
7824     {
7825       if(coords!=(*iter)->getCoords())
7826         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7827       if(meshDim!=(*iter)->getMeshDimension())
7828         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7829       meshLgth+=(*iter)->getMeshLength();
7830       meshIndexLgth+=(*iter)->getNumberOfCells();
7831     }
7832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7833   nodal->alloc(meshLgth,1);
7834   int *nodalPtr=nodal->getPointer();
7835   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7836   nodalIndex->alloc(meshIndexLgth+1,1);
7837   int *nodalIndexPtr=nodalIndex->getPointer();
7838   int offset=0;
7839   for(iter=meshes.begin();iter!=meshes.end();iter++)
7840     {
7841       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7842       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7843       int nbOfCells=(*iter)->getNumberOfCells();
7844       int meshLgth2=(*iter)->getMeshLength();
7845       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7846       if(iter!=meshes.begin())
7847         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7848       else
7849         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7850       offset+=meshLgth2;
7851     }
7852   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7853   ret->setName("merge");
7854   ret->setMeshDimension(meshDim);
7855   ret->setConnectivity(nodal,nodalIndex,true);
7856   ret->setCoords(coords);
7857   return ret;
7858 }
7859
7860 /*!
7861  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7862  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7863  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7864  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7865  * New" mode are returned for each input mesh.
7866  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7867  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7868  *          valid values [0,1,2], see zipConnectivityTraducer().
7869  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7870  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7871  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7872  *          no more needed.
7873  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7874  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7875  *          is no more needed.
7876  *  \throw If \a meshes.size() == 0.
7877  *  \throw If \a meshes[ *i* ] == NULL.
7878  *  \throw If the meshes do not share the node coordinates array.
7879  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7880  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7881  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7882  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7883  */
7884 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7885 {
7886   //All checks are delegated to MergeUMeshesOnSameCoords
7887   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7888   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7889   corr.resize(meshes.size());
7890   std::size_t nbOfMeshes=meshes.size();
7891   int offset=0;
7892   const int *o2nPtr=o2n->getConstPointer();
7893   for(std::size_t i=0;i<nbOfMeshes;i++)
7894     {
7895       DataArrayInt *tmp=DataArrayInt::New();
7896       int curNbOfCells=meshes[i]->getNumberOfCells();
7897       tmp->alloc(curNbOfCells,1);
7898       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7899       offset+=curNbOfCells;
7900       tmp->setName(meshes[i]->getName());
7901       corr[i]=tmp;
7902     }
7903   return ret.retn();
7904 }
7905
7906 /*!
7907  * Makes all given meshes share the nodal connectivity array. The common connectivity
7908  * array is created by concatenating the connectivity arrays of all given meshes. All
7909  * the given meshes must be of the same space dimension but dimension of cells **can
7910  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7911  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7912  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7913  *  \param [in,out] meshes - a vector of meshes to update.
7914  *  \throw If any of \a meshes is NULL.
7915  *  \throw If the coordinates array is not set in any of \a meshes.
7916  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7917  *  \throw If \a meshes are of different space dimension.
7918  */
7919 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7920 {
7921   std::size_t sz=meshes.size();
7922   if(sz==0 || sz==1)
7923     return;
7924   std::vector< const DataArrayDouble * > coords(meshes.size());
7925   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7926   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7927     {
7928       if((*it))
7929         {
7930           (*it)->checkConnectivityFullyDefined();
7931           const DataArrayDouble *coo=(*it)->getCoords();
7932           if(coo)
7933             *it2=coo;
7934           else
7935             {
7936               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7937               oss << " has no coordinate array defined !";
7938               throw INTERP_KERNEL::Exception(oss.str().c_str());
7939             }
7940         }
7941       else
7942         {
7943           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7944           oss << " is null !";
7945           throw INTERP_KERNEL::Exception(oss.str().c_str());
7946         }
7947     }
7948   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7949   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7950   int offset=(*it)->getNumberOfNodes();
7951   (*it++)->setCoords(res);
7952   for(;it!=meshes.end();it++)
7953     {
7954       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7955       (*it)->setCoords(res);
7956       (*it)->shiftNodeNumbersInConn(offset);
7957       offset+=oldNumberOfNodes;
7958     }
7959 }
7960
7961 /*!
7962  * Merges nodes coincident with a given precision within all given meshes that share
7963  * the nodal connectivity array. The given meshes **can be of different** mesh
7964  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7965  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7966  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7967  *  \param [in,out] meshes - a vector of meshes to update.
7968  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7969  *  \throw If any of \a meshes is NULL.
7970  *  \throw If the \a meshes do not share the same node coordinates array.
7971  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7972  */
7973 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7974 {
7975   if(meshes.empty())
7976     return ;
7977   std::set<const DataArrayDouble *> s;
7978   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7979     {
7980       if(*it)
7981         s.insert((*it)->getCoords());
7982       else
7983         {
7984           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 !";
7985           throw INTERP_KERNEL::Exception(oss.str().c_str());
7986         }
7987     }
7988   if(s.size()!=1)
7989     {
7990       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 !";
7991       throw INTERP_KERNEL::Exception(oss.str().c_str());
7992     }
7993   const DataArrayDouble *coo=*(s.begin());
7994   if(!coo)
7995     return;
7996   //
7997   DataArrayInt *comm,*commI;
7998   coo->findCommonTuples(eps,-1,comm,commI);
7999   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8000   int oldNbOfNodes=coo->getNumberOfTuples();
8001   int newNbOfNodes;
8002   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8003   if(oldNbOfNodes==newNbOfNodes)
8004     return ;
8005   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8006   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8007     {
8008       (*it)->renumberNodesInConn(o2n->getConstPointer());
8009       (*it)->setCoords(newCoords);
8010     } 
8011 }
8012
8013 /*!
8014  * 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.
8015  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8016  * \param isQuad specifies the policy of connectivity.
8017  * @ret in/out parameter in which the result will be append
8018  */
8019 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8020 {
8021   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8022   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8023   ret.push_back(cm.getExtrudedType());
8024   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8025   switch(flatType)
8026   {
8027     case INTERP_KERNEL::NORM_POINT1:
8028       {
8029         ret.push_back(connBg[1]);
8030         ret.push_back(connBg[1]+nbOfNodesPerLev);
8031         break;
8032       }
8033     case INTERP_KERNEL::NORM_SEG2:
8034       {
8035         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8036         ret.insert(ret.end(),conn,conn+4);
8037         break;
8038       }
8039     case INTERP_KERNEL::NORM_SEG3:
8040       {
8041         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8042         ret.insert(ret.end(),conn,conn+8);
8043         break;
8044       }
8045     case INTERP_KERNEL::NORM_QUAD4:
8046       {
8047         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8048         ret.insert(ret.end(),conn,conn+8);
8049         break;
8050       }
8051     case INTERP_KERNEL::NORM_TRI3:
8052       {
8053         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8054         ret.insert(ret.end(),conn,conn+6);
8055         break;
8056       }
8057     case INTERP_KERNEL::NORM_TRI6:
8058       {
8059         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,
8060           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8061         ret.insert(ret.end(),conn,conn+15);
8062         break;
8063       }
8064     case INTERP_KERNEL::NORM_QUAD8:
8065       {
8066         int conn[20]={
8067           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8068           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8069           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8070         };
8071         ret.insert(ret.end(),conn,conn+20);
8072         break;
8073       }
8074     case INTERP_KERNEL::NORM_POLYGON:
8075       {
8076         std::back_insert_iterator< std::vector<int> > ii(ret);
8077         std::copy(connBg+1,connEnd,ii);
8078         *ii++=-1;
8079         std::reverse_iterator<const int *> rConnBg(connEnd);
8080         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8081         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8082         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8083         for(std::size_t i=0;i<nbOfRadFaces;i++)
8084           {
8085             *ii++=-1;
8086             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8087             std::copy(conn,conn+4,ii);
8088           }
8089         break;
8090       }
8091     default:
8092       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8093   }
8094 }
8095
8096 /*!
8097  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8098  */
8099 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8100 {
8101   std::size_t i, ip1;
8102   double v[3]={0.,0.,0.};
8103   std::size_t sz=std::distance(begin,end);
8104   if(isQuadratic)
8105     sz/=2;
8106   for(i=0;i<sz;i++)
8107     {
8108       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];
8109       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8110       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8111     }
8112   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8113
8114   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8115   // SEG3 forming a circle):
8116   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8117     {
8118       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8119       for(std::size_t j=0;j<sz;j++)
8120         {
8121           if (j%2)  // current point i is quadratic, next point i+1 is standard
8122             {
8123               i = sz+j;
8124               ip1 = (j+1)%sz; // ip1 = "i+1"
8125             }
8126           else      // current point i is standard, next point i+1 is quadratic
8127             {
8128               i = j;
8129               ip1 = j+sz;
8130             }
8131           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8132           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8133           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8134         }
8135       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8136     }
8137   return (ret>0.);
8138 }
8139
8140 /*!
8141  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8142  */
8143 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8144 {
8145   std::vector<std::pair<int,int> > edges;
8146   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8147   const int *bgFace=begin;
8148   for(std::size_t i=0;i<nbOfFaces;i++)
8149     {
8150       const int *endFace=std::find(bgFace+1,end,-1);
8151       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8152       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8153         {
8154           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8155           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8156             return false;
8157           edges.push_back(p1);
8158         }
8159       bgFace=endFace+1;
8160     }
8161   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8162 }
8163
8164 /*!
8165  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8166  */
8167 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8168 {
8169   double vec0[3],vec1[3];
8170   std::size_t sz=std::distance(begin,end);
8171   if(sz%2!=0)
8172     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8173   int nbOfNodes=(int)sz/2;
8174   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8175   const double *pt0=coords+3*begin[0];
8176   const double *pt1=coords+3*begin[nbOfNodes];
8177   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8178   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8179 }
8180
8181 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8182 {
8183   std::size_t sz=std::distance(begin,end);
8184   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8185   std::size_t nbOfNodes(sz/2);
8186   std::copy(begin,end,(int *)tmp);
8187   for(std::size_t j=1;j<nbOfNodes;j++)
8188     {
8189       begin[j]=tmp[nbOfNodes-j];
8190       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8191     }
8192 }
8193
8194 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8195 {
8196   std::size_t sz=std::distance(begin,end);
8197   if(sz!=4)
8198     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8199   double vec0[3],vec1[3];
8200   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8201   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]; 
8202   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;
8203 }
8204
8205 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8206 {
8207   std::size_t sz=std::distance(begin,end);
8208   if(sz!=5)
8209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8210   double vec0[3];
8211   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8212   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8213   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8214 }
8215
8216 /*!
8217  * 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 ) 
8218  * 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
8219  * a 2D space.
8220  *
8221  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8222  * \param [in] coords the coordinates with nb of components exactly equal to 3
8223  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8224  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8225  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8226  */
8227 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8228 {
8229   int nbFaces=std::count(begin+1,end,-1)+1;
8230   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8231   double *vPtr=v->getPointer();
8232   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8233   double *pPtr=p->getPointer();
8234   const int *stFaceConn=begin+1;
8235   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8236     {
8237       const int *endFaceConn=std::find(stFaceConn,end,-1);
8238       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8239       stFaceConn=endFaceConn+1;
8240     }
8241   pPtr=p->getPointer(); vPtr=v->getPointer();
8242   DataArrayInt *comm1=0,*commI1=0;
8243   v->findCommonTuples(eps,-1,comm1,commI1);
8244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8245   const int *comm1Ptr=comm1->getConstPointer();
8246   const int *commI1Ptr=commI1->getConstPointer();
8247   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8248   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8249   //
8250   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8251   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8252   mm->finishInsertingCells();
8253   //
8254   for(int i=0;i<nbOfGrps1;i++)
8255     {
8256       int vecId=comm1Ptr[commI1Ptr[i]];
8257       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8258       DataArrayInt *comm2=0,*commI2=0;
8259       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8260       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8261       const int *comm2Ptr=comm2->getConstPointer();
8262       const int *commI2Ptr=commI2->getConstPointer();
8263       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8264       for(int j=0;j<nbOfGrps2;j++)
8265         {
8266           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8267             {
8268               res->insertAtTheEnd(begin,end);
8269               res->pushBackSilent(-1);
8270             }
8271           else
8272             {
8273               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8274               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8275               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8276               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8277               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8278               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8279               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8280               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8281               const int *idsNodePtr=idsNode->getConstPointer();
8282               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];
8283               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8284               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8285               if(std::abs(norm)>eps)
8286                 {
8287                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8288                   mm3->rotate(center,vec,angle);
8289                 }
8290               mm3->changeSpaceDimension(2);
8291               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8292               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8293               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8294               int nbOfCells=mm4->getNumberOfCells();
8295               for(int k=0;k<nbOfCells;k++)
8296                 {
8297                   int l=0;
8298                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8299                     res->pushBackSilent(idsNodePtr[*work]);
8300                   res->pushBackSilent(-1);
8301                 }
8302             }
8303         }
8304     }
8305   res->popBackSilent();
8306 }
8307
8308 /*!
8309  * 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
8310  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8311  * 
8312  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8313  * \param [in] coords coordinates expected to have 3 components.
8314  * \param [in] begin start of the nodal connectivity of the face.
8315  * \param [in] end end of the nodal connectivity (excluded) of the face.
8316  * \param [out] v the normalized vector of size 3
8317  * \param [out] p the pos of plane
8318  */
8319 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8320 {
8321   std::size_t nbPoints=std::distance(begin,end);
8322   if(nbPoints<3)
8323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8324   double vec[3]={0.,0.,0.};
8325   std::size_t j=0;
8326   bool refFound=false;
8327   for(;j<nbPoints-1 && !refFound;j++)
8328     {
8329       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8330       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8331       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8332       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8333       if(norm>eps)
8334         {
8335           refFound=true;
8336           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8337         }
8338     }
8339   for(std::size_t i=j;i<nbPoints-1;i++)
8340     {
8341       double curVec[3];
8342       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8343       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8344       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8345       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8346       if(norm<eps)
8347         continue;
8348       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8349       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];
8350       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8351       if(norm>eps)
8352         {
8353           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8354           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8355           return ;
8356         }
8357     }
8358   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8359 }
8360
8361 /*!
8362  * This method tries to obtain a well oriented polyhedron.
8363  * If the algorithm fails, an exception will be thrown.
8364  */
8365 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8366 {
8367   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8368   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8369   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8370   isPerm[0]=true;
8371   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8372   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8373   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8374   //
8375   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8376     {
8377       bgFace=begin;
8378       std::size_t smthChanged=0;
8379       for(std::size_t i=0;i<nbOfFaces;i++)
8380         {
8381           endFace=std::find(bgFace+1,end,-1);
8382           nbOfEdgesInFace=std::distance(bgFace,endFace);
8383           if(!isPerm[i])
8384             {
8385               bool b;
8386               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8387                 {
8388                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8389                   std::pair<int,int> p2(p1.second,p1.first);
8390                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8391                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8392                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8393                 }
8394               if(isPerm[i])
8395                 { 
8396                   if(!b)
8397                     std::reverse(bgFace+1,endFace);
8398                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8399                     {
8400                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8401                       std::pair<int,int> p2(p1.second,p1.first);
8402                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8403                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8404                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8405                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8406                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8407                       if(it!=edgesOK.end())
8408                         {
8409                           edgesOK.erase(it);
8410                           edgesFinished.push_back(p1);
8411                         }
8412                       else
8413                         edgesOK.push_back(p1);
8414                     }
8415                 }
8416             }
8417           bgFace=endFace+1;
8418         }
8419       if(smthChanged==0)
8420         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8421     }
8422   if(!edgesOK.empty())
8423     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8424   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8425     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8426       bgFace=begin;
8427       for(std::size_t i=0;i<nbOfFaces;i++)
8428         {
8429           endFace=std::find(bgFace+1,end,-1);
8430           std::reverse(bgFace+1,endFace);
8431           bgFace=endFace+1;
8432         }
8433     }
8434 }
8435
8436 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8437 {
8438   int nbOfNodesExpected(skin->getNumberOfNodes());
8439   const int *n2oPtr(n2o->getConstPointer());
8440   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8441   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8442   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8443   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8444   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8445   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8446   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8447   if(nbOfNodesExpected<1)
8448     return ret.retn();
8449   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8450   *work++=n2oPtr[prevNode];
8451   for(int i=1;i<nbOfNodesExpected;i++)
8452     {
8453       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8454         {
8455           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8456           conn.erase(prevNode);
8457           if(conn.size()==1)
8458             {
8459               int curNode(*(conn.begin()));
8460               *work++=n2oPtr[curNode];
8461               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8462               shar.erase(prevCell);
8463               if(shar.size()==1)
8464                 {
8465                   prevCell=*(shar.begin());
8466                   prevNode=curNode;
8467                 }
8468               else
8469                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8470             }
8471           else
8472             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8473         }
8474       else
8475         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8476     }
8477   return ret.retn();
8478 }
8479
8480 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8481 {
8482   int nbOfNodesExpected(skin->getNumberOfNodes());
8483   int nbOfTurn(nbOfNodesExpected/2);
8484   const int *n2oPtr(n2o->getConstPointer());
8485   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8486   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8487   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8488   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8489   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8491   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8492   if(nbOfNodesExpected<1)
8493     return ret.retn();
8494   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8495   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8496   for(int i=1;i<nbOfTurn;i++)
8497     {
8498       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8499         {
8500           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8501           conn.erase(prevNode);
8502           if(conn.size()==1)
8503             {
8504               int curNode(*(conn.begin()));
8505               *work=n2oPtr[curNode];
8506               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8507               shar.erase(prevCell);
8508               if(shar.size()==1)
8509                 {
8510                   int curCell(*(shar.begin()));
8511                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8512                   prevCell=curCell;
8513                   prevNode=curNode;
8514                   work++;
8515                 }
8516               else
8517                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8518             }
8519           else
8520             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8521         }
8522       else
8523         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8524     }
8525   return ret.retn();
8526 }
8527
8528 /*!
8529  * This method makes the assumption spacedimension == meshdimension == 2.
8530  * This method works only for linear cells.
8531  * 
8532  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8533  */
8534 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8535 {
8536   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8537     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8538   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8539   int oldNbOfNodes(skin->getNumberOfNodes());
8540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8541   int nbOfNodesExpected(skin->getNumberOfNodes());
8542   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8543   int nbCells(skin->getNumberOfCells());
8544   if(nbCells==nbOfNodesExpected)
8545     return buildUnionOf2DMeshLinear(skin,n2o);
8546   else if(2*nbCells==nbOfNodesExpected)
8547     return buildUnionOf2DMeshQuadratic(skin,n2o);
8548   else
8549     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8550 }
8551
8552 /*!
8553  * This method makes the assumption spacedimension == meshdimension == 3.
8554  * This method works only for linear cells.
8555  * 
8556  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8557  */
8558 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8559 {
8560   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8562   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8563   const int *conn=m->getNodalConnectivity()->getConstPointer();
8564   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8565   int nbOfCells=m->getNumberOfCells();
8566   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8567   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8568   if(nbOfCells<1)
8569     return ret.retn();
8570   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8571   for(int i=1;i<nbOfCells;i++)
8572     {
8573       *work++=-1;
8574       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8575     }
8576   return ret.retn();
8577 }
8578
8579 /*!
8580  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8581  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8582  */
8583 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8584 {
8585   double *w=zipFrmt;
8586   if(spaceDim==3)
8587     for(int i=0;i<nbOfNodesInCell;i++)
8588       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8589   else if(spaceDim==2)
8590     {
8591       for(int i=0;i<nbOfNodesInCell;i++)
8592         {
8593           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8594           *w++=0.;
8595         }
8596     }
8597   else
8598     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8599 }
8600
8601 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8602 {
8603   int nbOfCells=getNumberOfCells();
8604   if(nbOfCells<=0)
8605     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8606   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};
8607   ofs << "  <" << getVTKDataSetType() << ">\n";
8608   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8609   ofs << "      <PointData>\n" << pointData << std::endl;
8610   ofs << "      </PointData>\n";
8611   ofs << "      <CellData>\n" << cellData << std::endl;
8612   ofs << "      </CellData>\n";
8613   ofs << "      <Points>\n";
8614   if(getSpaceDimension()==3)
8615     _coords->writeVTK(ofs,8,"Points",byteData);
8616   else
8617     {
8618       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8619       coo->writeVTK(ofs,8,"Points",byteData);
8620     }
8621   ofs << "      </Points>\n";
8622   ofs << "      <Cells>\n";
8623   const int *cPtr=_nodal_connec->getConstPointer();
8624   const int *cIPtr=_nodal_connec_index->getConstPointer();
8625   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8626   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8627   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8628   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8629   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8630   int szFaceOffsets=0,szConn=0;
8631   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8632     {
8633       *w2=cPtr[cIPtr[i]];
8634       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8635         {
8636           *w1=-1;
8637           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8638           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8639         }
8640       else
8641         {
8642           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8643           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8644           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8645           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8646           w4=std::copy(c.begin(),c.end(),w4);
8647         }
8648     }
8649   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8650   types->writeVTK(ofs,8,"UInt8","types",byteData);
8651   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8652   if(szFaceOffsets!=0)
8653     {//presence of Polyhedra
8654       connectivity->reAlloc(szConn);
8655       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8656       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8657       w1=faces->getPointer();
8658       for(int i=0;i<nbOfCells;i++)
8659         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8660           {
8661             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8662             *w1++=nbFaces;
8663             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8664             for(int j=0;j<nbFaces;j++)
8665               {
8666                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8667                 *w1++=(int)std::distance(w6,w5);
8668                 w1=std::copy(w6,w5,w1);
8669                 w6=w5+1;
8670               }
8671           }
8672       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8673     }
8674   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8675   ofs << "      </Cells>\n";
8676   ofs << "    </Piece>\n";
8677   ofs << "  </" << getVTKDataSetType() << ">\n";
8678 }
8679
8680 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8681 {
8682   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8683   if(_mesh_dim==-2)
8684     { stream << " Not set !"; return ; }
8685   stream << " Mesh dimension : " << _mesh_dim << ".";
8686   if(_mesh_dim==-1)
8687     return ;
8688   if(!_coords)
8689     { stream << " No coordinates set !"; return ; }
8690   if(!_coords->isAllocated())
8691     { stream << " Coordinates set but not allocated !"; return ; }
8692   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8693   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8694   if(!_nodal_connec_index)
8695     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8696   if(!_nodal_connec_index->isAllocated())
8697     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8698   int lgth=_nodal_connec_index->getNumberOfTuples();
8699   int cpt=_nodal_connec_index->getNumberOfComponents();
8700   if(cpt!=1 || lgth<1)
8701     return ;
8702   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8703 }
8704
8705 std::string MEDCouplingUMesh::getVTKDataSetType() const
8706 {
8707   return std::string("UnstructuredGrid");
8708 }
8709
8710 std::string MEDCouplingUMesh::getVTKFileExtension() const
8711 {
8712   return std::string("vtu");
8713 }
8714
8715 /*!
8716  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8717  * returns a result mesh constituted by polygons.
8718  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8719  * all nodes from m2.
8720  * The meshes should be in 2D space. In
8721  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8722  * meshes.
8723  *  \param [in] m1 - the first input mesh which is a partitioned object.
8724  *  \param [in] m2 - the second input mesh which is a partition tool.
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 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8742                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8743 {
8744   if(!m1 || !m2)
8745     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8746   m1->checkFullyDefined();
8747   m2->checkFullyDefined();
8748   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8749     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8750
8751   // Step 1: compute all edge intersections (new nodes)
8752   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8753   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8754   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8755   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8756   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8757                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8758                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8759   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8761   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8762
8763   // Step 2: re-order newly created nodes according to the ordering found in m2
8764   std::vector< std::vector<int> > intersectEdge2;
8765   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8766   subDiv2.clear(); dd5=0; dd6=0;
8767
8768   // Step 3:
8769   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8770   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8771   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8772                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8773
8774   // Step 4: Prepare final result:
8775   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8776   addCooDa->alloc((int)(addCoo.size())/2,2);
8777   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8778   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8779   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8780   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8781   std::vector<const DataArrayDouble *> coordss(4);
8782   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8783   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8784   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8785   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8786   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8788   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8789   ret->setConnectivity(conn,connI,true);
8790   ret->setCoords(coo);
8791   cellNb1=c1.retn(); cellNb2=c2.retn();
8792   return ret.retn();
8793 }
8794
8795 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8796 {
8797   if(candidates.empty())
8798     return false;
8799   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8800     {
8801       const std::vector<int>& pool(intersectEdge1[*it]);
8802       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8803       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8804         {
8805           retVal=*it+1;
8806           return true;
8807         }
8808       tmp[0]=stop; tmp[1]=start;
8809       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8810         {
8811           retVal=-*it-1;
8812           return true;
8813         }
8814     }
8815   return false;
8816 }
8817
8818 //tony to put in private of MEDCouplingUMesh
8819 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,
8820                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8821 {
8822   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8823   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8824   int nCells(mesh1D->getNumberOfCells());
8825   if(nCells!=(int)intersectEdge2.size())
8826     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8827   const DataArrayDouble *coo2(mesh1D->getCoords());
8828   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8829   const double *coo2Ptr(coo2->begin());
8830   int offset1(coords1->getNumberOfTuples());
8831   int offset2(offset1+coo2->getNumberOfTuples());
8832   int offset3(offset2+addCoo.size()/2);
8833   std::vector<double> addCooQuad;
8834   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8835   int tmp[4],cicnt(0),kk(0);
8836   for(int i=0;i<nCells;i++)
8837     {
8838       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8839       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8840       const std::vector<int>& subEdges(intersectEdge2[i]);
8841       int nbSubEdge(subEdges.size()/2);
8842       for(int j=0;j<nbSubEdge;j++,kk++)
8843         {
8844           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));
8845           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8846           INTERP_KERNEL::Edge *e2Ptr(e2);
8847           std::map<int,int>::const_iterator itm;
8848           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8849             {
8850               tmp[0]=INTERP_KERNEL::NORM_SEG3;
8851               itm=mergedNodes.find(subEdges[2*j]);
8852               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8853               itm=mergedNodes.find(subEdges[2*j+1]);
8854               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8855               tmp[3]=offset3+(int)addCooQuad.size()/2;
8856               double tmp2[2];
8857               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8858               cicnt+=4;
8859               cOut->insertAtTheEnd(tmp,tmp+4);
8860               ciOut->pushBackSilent(cicnt);
8861             }
8862           else
8863             {
8864               tmp[0]=INTERP_KERNEL::NORM_SEG2;
8865               itm=mergedNodes.find(subEdges[2*j]);
8866               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8867               itm=mergedNodes.find(subEdges[2*j+1]);
8868               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8869               cicnt+=3;
8870               cOut->insertAtTheEnd(tmp,tmp+3);
8871               ciOut->pushBackSilent(cicnt);
8872             }
8873           int tmp00;
8874           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8875             {
8876               idsInRetColinear->pushBackSilent(kk);
8877               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8878             }
8879         }
8880       e->decrRef();
8881     }
8882   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8883   ret->setConnectivity(cOut,ciOut,true);
8884   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8885   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8886   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8887   std::vector<const DataArrayDouble *> coordss(4);
8888   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8889   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8890   ret->setCoords(arr);
8891   return ret.retn();
8892 }
8893
8894 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8895 {
8896   std::vector<int> allEdges;
8897   for(const int *it2(descBg);it2!=descEnd;it2++)
8898     {
8899       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8900       if(*it2>0)
8901         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8902       else
8903         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8904     }
8905   std::size_t nb(allEdges.size());
8906   if(nb%2!=0)
8907     throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !");
8908   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8909   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8910   ret->setCoords(coords);
8911   ret->allocateCells(1);
8912   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8913   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8914     connOut[kk]=allEdges[2*kk];
8915   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8916   return ret.retn();
8917 }
8918
8919 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
8920 {
8921   bool isQuad(false);
8922   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
8923     {
8924       const INTERP_KERNEL::Edge *ee(*it);
8925       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
8926         isQuad=true;
8927     }
8928   if(!isQuad)
8929     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
8930   else
8931     {
8932       const double *coo(mesh2D->getCoords()->begin());
8933       std::size_t sz(conn.size());
8934       std::vector<double> addCoo;
8935       std::vector<int> conn2(conn);
8936       int offset(mesh2D->getNumberOfNodes());
8937       for(std::size_t i=0;i<sz;i++)
8938         {
8939           double tmp[2];
8940           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);
8941           addCoo.insert(addCoo.end(),tmp,tmp+2);
8942           conn2.push_back(offset+(int)i);
8943         }
8944       mesh2D->getCoords()->rearrange(1);
8945       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
8946       mesh2D->getCoords()->rearrange(2);
8947       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
8948     }
8949 }
8950
8951 MEDCouplingUMesh *BuildMesh2DCutFrom(int cellIdInMesh2D, const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
8952                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
8953                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
8954 {
8955   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(splitMesh1D->getNumberOfCells(),2);
8956   int *idsLeftRightPtr(idsLeftRight->getPointer());
8957   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8958   ret->setCoords(splitMesh1D->getCoords());
8959   ret->allocateCells();
8960   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
8961   if(nbCellsInSplitMesh1D==0)
8962     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error ! input 1D mesh must have at least one cell !");
8963   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin()),
8964       *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
8965   //
8966   std::vector<int> allEdges;
8967   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr;
8968   for(const int *it(descBg);it!=descEnd;it++)
8969     {
8970       int edgeId(std::abs(*it)-1);
8971       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8972       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
8973       const std::vector<int>& edge1(intersectEdge1[edgeId]);
8974       if(*it>0)
8975         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8976       else
8977         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8978       std::size_t sz(edge1.size());
8979       for(std::size_t cnt=0;cnt<sz;cnt++)
8980         allEdgesPtr.push_back(ee);
8981     }
8982   std::size_t nb(allEdges.size()),ii,jj;
8983   if(nb%2!=0)
8984     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
8985   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8986   std::vector<int> edge1Bis(nb*2);
8987   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
8988   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
8989   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
8990   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
8991   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
8992   //
8993   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
8994     {
8995       int iEnd(iStart);
8996       for(;iEnd<nbCellsInSplitMesh1D;)
8997         {
8998           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
8999           if(jj!=nb)
9000             break;
9001           else
9002             iEnd++;
9003         }
9004       if(iEnd<nbCellsInSplitMesh1D)
9005         iEnd++;
9006       //
9007       for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[iStart]+1];ii++);
9008       for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9009       //
9010       if(jj==nb)
9011         {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9012           std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9013           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr(nbOfEdgesOf2DCellSplit);
9014           for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9015             {
9016               connOut[kk]=edge1Bis[2*kk];
9017               edgesPtr[kk]=edge1BisPtr[2*kk];
9018             }
9019           AddCellInMesh2D(ret,connOut,edgesPtr);
9020           for(int mm=iStart;mm<iEnd;mm++)
9021             {
9022               idsLeftRightPtr[2*mm]=offset;
9023               idsLeftRightPtr[2*mm+1]=offset;
9024             }
9025         }
9026       else
9027         {
9028           // [i,iEnd[ contains the
9029           std::vector<int> connOutLeft,connOutRight;//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9030           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > eleft,eright;
9031           for(std::size_t k=ii;k<jj+1;k++)
9032             { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9033           for(int ik=iEnd-1;ik>=iStart;ik--)
9034             {
9035               connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9036               std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9037               MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9038               eleft.push_back(ee);
9039             }
9040           for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9041             { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9042           for(int ik=iStart;ik<iEnd;ik++)
9043             {
9044               std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9045               connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9046               MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9047               eright.push_back(ee);
9048             }
9049           AddCellInMesh2D(ret,connOutLeft,eleft);
9050           AddCellInMesh2D(ret,connOutRight,eright);
9051           for(int mm=iStart;mm<iEnd;mm++)
9052             {
9053               idsLeftRightPtr[2*mm]=offset;
9054               idsLeftRightPtr[2*mm+1]=offset+1;
9055             }
9056         }
9057       //
9058       iStart=iEnd;
9059     }
9060   return ret.retn();
9061 }
9062
9063 /*!
9064  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9065  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
9066  * all nodes from \a mesh1D.
9067  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9068  *
9069  * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool.
9070  * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D.
9071  * \param [in] eps - precision used to perform intersections and localization operations.
9072  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9073  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9074  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9075  *                               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.
9076  * \param [out] cellIdInMesh1D - the array that gives for each cell id \a i in \a splitMesh1D the 1 or 2 id(s) in \a splitMesh2D that \a i shares.
9077  *                               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.
9078  */
9079 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9080 {
9081   if(!mesh2D || !mesh1D)
9082     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9083   mesh2D->checkFullyDefined();
9084   mesh1D->checkFullyDefined();
9085   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9086   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9088   // Step 1: compute all edge intersections (new nodes)
9089   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9090   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9091   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9092   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9093   //
9094   // Build desc connectivity
9095   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9096   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9097   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9098   std::map<int,int> mergedNodes;
9099   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9100   // use mergeNodes to fix intersectEdge1
9101   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9102     {
9103       std::size_t n((*it0).size()/2);
9104       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9105       std::map<int,int>::const_iterator it1;
9106       it1=mergedNodes.find(eltStart);
9107       if(it1!=mergedNodes.end())
9108         (*it0)[0]=(*it1).second;
9109       it1=mergedNodes.find(eltEnd);
9110       if(it1!=mergedNodes.end())
9111         (*it0)[2*n-1]=(*it1).second;
9112     }
9113   //
9114   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9115   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9116   // Step 2: re-order newly created nodes according to the ordering found in m2
9117   std::vector< std::vector<int> > intersectEdge2;
9118   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9119   subDiv2.clear();
9120   //
9121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9122   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9123   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9124       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9125   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2);
9126   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9127   // deal with cells in mesh2D that are not cut but only some of their edges are
9128   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9129   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9130   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9131   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of those cells
9132   if(!idsInDesc2DToBeRefined->empty())
9133     {
9134       DataArrayInt *out0(0),*outi0(0);
9135       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9136       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9137       out0s=out0;
9138       out0s=out0s->buildUnique();
9139       out0s->sort(true);
9140     }
9141   //
9142   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9143   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9144   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9145   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9147   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9148   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9149     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9150   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9151   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9152   if((DataArrayInt *)out0s)
9153     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9154   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9155   if(!untouchedCells->empty())
9156     {
9157       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9158       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9159       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9160     }
9161   if((DataArrayInt *)out0s)
9162     {// here dealing with cells in out0s but not in cellsToBeModified
9163       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9164       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9165       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9166         {
9167           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9168         }
9169       int offset(ret2->getNumberOfTuples());
9170       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9171       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9172       partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2);
9173       int kk(0),*ret3ptr(partOfRet3->getPointer());
9174       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9175         {
9176           int faceId(std::abs(*it)-1);
9177           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9178             {
9179               int tmp(fewModifiedCells->locateValue(*it2));
9180               if(tmp!=-1)
9181                 {
9182                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9183                     ret3ptr[2*kk]=tmp+offset;
9184                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9185                     ret3ptr[2*kk+1]=tmp+offset;
9186                 }
9187               else
9188                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !");
9189             }
9190         }
9191       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9192     }
9193   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9194     {
9195       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9196       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9197       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9198       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9199       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9200       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(*it,mesh2D,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9201       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9202       outMesh2DSplit.push_back(splitOfOneCell);
9203       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9204         ret2->pushBackSilent(*it);
9205     }
9206   //
9207   std::size_t nbOfMeshes(outMesh2DSplit.size());
9208   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9209   for(std::size_t i=0;i<nbOfMeshes;i++)
9210     tmp[i]=outMesh2DSplit[i];
9211   //
9212   ret1->getCoords()->setInfoOnComponents(compNames);
9213   //
9214   splitMesh1D=ret1.retn();
9215   splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp);
9216   cellIdInMesh2D=ret2.retn();
9217   cellIdInMesh1D=ret3.retn();
9218 }
9219
9220 /**
9221  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9222  * (newly created) nodes corresponding to the edge intersections.
9223  * Output params:
9224  * @param[out] cr, crI connectivity of the resulting mesh
9225  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9226  * TODO: describe input parameters
9227  */
9228 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9229                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9230                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9231                                                          const std::vector<double>& addCoords,
9232                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9233 {
9234   static const int SPACEDIM=2;
9235   const double *coo1(m1->getCoords()->getConstPointer());
9236   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9237   int offset1(m1->getNumberOfNodes());
9238   const double *coo2(m2->getCoords()->getConstPointer());
9239   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9240   int offset2(offset1+m2->getNumberOfNodes());
9241   int offset3(offset2+((int)addCoords.size())/2);
9242   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9243   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9244   // Here a BBTree on 2D-cells, not on segments:
9245   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9246   int ncell1(m1->getNumberOfCells());
9247   crI.push_back(0);
9248   for(int i=0;i<ncell1;i++)
9249     {
9250       std::vector<int> candidates2;
9251       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9252       std::map<INTERP_KERNEL::Node *,int> mapp;
9253       std::map<int,INTERP_KERNEL::Node *> mappRev;
9254       INTERP_KERNEL::QuadraticPolygon pol1;
9255       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9256       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9257       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9258       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9259       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9260       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9261           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9262       //
9263       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
9264       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9265       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9266       for(it1.first();!it1.finished();it1.next())
9267         edges1.insert(it1.current()->getPtr());
9268       //
9269       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9270       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9271       int ii=0;
9272       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9273         {
9274           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9275           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9276           // Complete mapping with elements coming from the current cell it2 in mesh2:
9277           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9278           // pol2 is the new QP in the final merged result.
9279           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9280               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9281         }
9282       ii=0;
9283       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9284         {
9285           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9286           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9287           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9288           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9289         }
9290       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9291       // by m2 but that we still want to keep in the final result.
9292       if(!edges1.empty())
9293         {
9294           try
9295           {
9296               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9297           }
9298           catch(INTERP_KERNEL::Exception& e)
9299           {
9300               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();
9301               throw INTERP_KERNEL::Exception(oss.str().c_str());
9302           }
9303         }
9304       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9305         (*it).second->decrRef();
9306     }
9307 }
9308
9309 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9310 {
9311   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9312   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9313   if(it==m.end())
9314     throw INTERP_KERNEL::Exception("Internal error in remapping !");
9315   int v((*it).second);
9316   if(v==forbVal0 || v==forbVal1)
9317     return ;
9318   if(std::find(isect.begin(),isect.end(),v)==isect.end())
9319     isect.push_back(v);
9320 }
9321
9322 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9323 {
9324   int sz(c.size());
9325   if(sz<=1)
9326     return false;
9327   bool presenceOfOn(false);
9328   for(int i=0;i<sz;i++)
9329     {
9330       INTERP_KERNEL::ElementaryEdge *e(c[i]);
9331       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9332         continue ;
9333       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9334       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9335     }
9336   return presenceOfOn;
9337 }
9338
9339 /**
9340  * 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.
9341  * 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.
9342  * 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.
9343  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9344  *
9345  * \return int - the number of new nodes created (in most of cases 0).
9346  * 
9347  * \throw If \a this is not coherent.
9348  * \throw If \a this has not spaceDim equal to 2.
9349  * \throw If \a this has not meshDim equal to 2.
9350  * \throw If some subcells needed to be split are orphan.
9351  * \sa MEDCouplingUMesh::conformize2D
9352  */
9353 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9354 {
9355   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9356     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9357   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9358   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9360   if(midOpt==0 && midOptI==0)
9361     {
9362       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9363       return 0;
9364     }
9365   else if(midOpt!=0 && midOptI!=0)
9366     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9367   else
9368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9369 }
9370
9371 /*!
9372  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9373  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9374  * 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
9375  * 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).
9376  * 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.
9377  * 
9378  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9379  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9380  *
9381  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9382  * This method expects that all nodes in \a this are not closer than \a eps.
9383  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9384  * 
9385  * \param [in] eps the relative error to detect merged edges.
9386  * \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
9387  *                           that the user is expected to deal with.
9388  *
9389  * \throw If \a this is not coherent.
9390  * \throw If \a this has not spaceDim equal to 2.
9391  * \throw If \a this has not meshDim equal to 2.
9392  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9393  */
9394 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9395 {
9396   static const int SPACEDIM=2;
9397   checkCoherency();
9398   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9399     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9402   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9403   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9404   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9405   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9406   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9407   std::vector<double> addCoo;
9408   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9409   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9410   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9411   for(int i=0;i<nDescCell;i++)
9412     {
9413       std::vector<int> candidates;
9414       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9415       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9416         if(*it>i)
9417           {
9418             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9419             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9420                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9421             INTERP_KERNEL::MergePoints merge;
9422             INTERP_KERNEL::QuadraticPolygon c1,c2;
9423             e1->intersectWith(e2,merge,c1,c2);
9424             e1->decrRef(); e2->decrRef();
9425             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9426               overlapEdge[i].push_back(*it);
9427             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9428               overlapEdge[*it].push_back(i);
9429           }
9430     }
9431   // splitting done. sort intersect point in intersectEdge.
9432   std::vector< std::vector<int> > middle(nDescCell);
9433   int nbOf2DCellsToBeSplit(0);
9434   bool middleNeedsToBeUsed(false);
9435   std::vector<bool> cells2DToTreat(nDescCell,false);
9436   for(int i=0;i<nDescCell;i++)
9437     {
9438       std::vector<int>& isect(intersectEdge[i]);
9439       int sz((int)isect.size());
9440       if(sz>1)
9441         {
9442           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9443           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9444           e->sortSubNodesAbs(coords,isect);
9445           e->decrRef();
9446         }
9447       if(sz!=0)
9448         {
9449           int idx0(rdi[i]),idx1(rdi[i+1]);
9450           if(idx1-idx0!=1)
9451             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9452           if(!cells2DToTreat[rd[idx0]])
9453             {
9454               cells2DToTreat[rd[idx0]]=true;
9455               nbOf2DCellsToBeSplit++;
9456             }
9457           // try to reuse at most eventual 'middle' of SEG3
9458           std::vector<int>& mid(middle[i]);
9459           mid.resize(sz+1,-1);
9460           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9461             {
9462               middleNeedsToBeUsed=true;
9463               const std::vector<int>& candidates(overlapEdge[i]);
9464               std::vector<int> trueCandidates;
9465               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9466                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9467                   trueCandidates.push_back(*itc);
9468               int stNode(c[ci[i]+1]),endNode(isect[0]);
9469               for(int j=0;j<sz+1;j++)
9470                 {
9471                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9472                     {
9473                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9474                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9475                         { mid[j]=*itc; break; }
9476                     }
9477                   stNode=endNode;
9478                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9479                 }
9480             }
9481         }
9482     }
9483   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9484   if(nbOf2DCellsToBeSplit==0)
9485     return ret.retn();
9486   //
9487   int *retPtr(ret->getPointer());
9488   for(int i=0;i<nCell;i++)
9489     if(cells2DToTreat[i])
9490       *retPtr++=i;
9491   //
9492   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9493   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9494   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9495   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9496   if(middleNeedsToBeUsed)
9497     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9498   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9499   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9500   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.
9501   setPartOfMySelf(ret->begin(),ret->end(),*modif);
9502   {
9503     bool areNodesMerged; int newNbOfNodes;
9504     if(nbOfNodesCreated!=0)
9505       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9506   }
9507   return ret.retn();
9508 }
9509
9510 /*!
9511  * 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.
9512  * 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).
9513  * 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
9514  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9515  * 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
9516  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9517  *
9518  * 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
9519  * using new instance, idem for coordinates.
9520  *
9521  * 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.
9522  * 
9523  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
9524  *
9525  * \throw If \a this is not coherent.
9526  * \throw If \a this has not spaceDim equal to 2.
9527  * \throw If \a this has not meshDim equal to 2.
9528  * 
9529  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9530  */
9531 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9532 {
9533   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9534   checkCoherency();
9535   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9536     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9537   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9538   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9539   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9540   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9541   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9542   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9543   const double *coords(_coords->begin());
9544   int *newciptr(newci->getPointer());
9545   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9546     {
9547       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9548         ret->pushBackSilent(i);
9549       newciptr[1]=newc->getNumberOfTuples();
9550     }
9551   //
9552   if(ret->empty())
9553     return ret.retn();
9554   if(!appendedCoords->empty())
9555     {
9556       appendedCoords->rearrange(2);
9557       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9558       //non const part
9559       setCoords(newCoords);
9560     }
9561   //non const part
9562   setConnectivity(newc,newci,true);
9563   return ret.retn();
9564 }
9565
9566 /*!
9567  * \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.
9568  *                               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.
9569  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9570  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9571  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9572  * \param [out] addCoo - nodes to be append at the end
9573  * \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.
9574  */
9575 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
9576                                          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)
9577 {
9578   static const int SPACEDIM=2;
9579   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9580   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9581   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
9582   // Build BB tree of all edges in the tool mesh (second mesh)
9583   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9584   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9585   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
9586   intersectEdge1.resize(nDescCell1);
9587   colinear2.resize(nDescCell2);
9588   subDiv2.resize(nDescCell2);
9589   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9590
9591   std::vector<int> candidates1(1);
9592   int offset1(m1Desc->getNumberOfNodes());
9593   int offset2(offset1+m2Desc->getNumberOfNodes());
9594   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
9595     {
9596       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9597       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9598       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9599         {
9600           std::map<INTERP_KERNEL::Node *,int> map1,map2;
9601           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9602           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9603           candidates1[0]=i;
9604           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9605           // 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
9606           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9607           std::set<INTERP_KERNEL::Node *> nodes;
9608           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9609           std::size_t szz(nodes.size());
9610           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9611           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9612           for(std::size_t iii=0;iii<szz;iii++,itt++)
9613             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9614           // end of protection
9615           // Performs egde cutting:
9616           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
9617           delete pol2;
9618           delete pol1;
9619         }
9620       else
9621         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9622     }
9623 }
9624
9625 /*!
9626  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
9627  * It builds the descending connectivity of the two meshes, and then using a binary tree
9628  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
9629  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
9630  */
9631 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
9632                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9633                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9634                                                    std::vector<double>& addCoo,
9635                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
9636 {
9637   // Build desc connectivity
9638   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
9639   desc2=DataArrayInt::New();
9640   descIndx2=DataArrayInt::New();
9641   revDesc2=DataArrayInt::New();
9642   revDescIndx2=DataArrayInt::New();
9643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
9645   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
9646   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
9647   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
9648   std::map<int,int> notUsedMap;
9649   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
9650   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9651   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9652 }
9653
9654 /*!
9655  * This method performs the 2nd step of Partition of 2D mesh.
9656  * This method has 4 inputs :
9657  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9658  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9659  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9660  * 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'
9661  * Nodes end up lying consecutively on a cutted edge.
9662  * \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.
9663  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9664  * \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.
9665  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9666  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9667  */
9668 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9669                                            const std::vector<double>& addCoo,
9670                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9671 {
9672   int offset1=m1->getNumberOfNodes();
9673   int ncell=m2->getNumberOfCells();
9674   const int *c=m2->getNodalConnectivity()->getConstPointer();
9675   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9676   const double *coo=m2->getCoords()->getConstPointer();
9677   const double *cooBis=m1->getCoords()->getConstPointer();
9678   int offset2=offset1+m2->getNumberOfNodes();
9679   intersectEdge.resize(ncell);
9680   for(int i=0;i<ncell;i++,cI++)
9681     {
9682       const std::vector<int>& divs=subDiv[i];
9683       int nnode=cI[1]-cI[0]-1;
9684       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9685       std::map<INTERP_KERNEL::Node *, int> mapp22;
9686       for(int j=0;j<nnode;j++)
9687         {
9688           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9689           int nnid=c[(*cI)+j+1];
9690           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9691           mapp22[nn]=nnid+offset1;
9692         }
9693       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9694       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9695         ((*it).second.first)->decrRef();
9696       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9697       std::map<INTERP_KERNEL::Node *,int> mapp3;
9698       for(std::size_t j=0;j<divs.size();j++)
9699         {
9700           int id=divs[j];
9701           INTERP_KERNEL::Node *tmp=0;
9702           if(id<offset1)
9703             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9704           else if(id<offset2)
9705             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9706           else
9707             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9708           addNodes[j]=tmp;
9709           mapp3[tmp]=id;
9710         }
9711       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9712       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9713         (*it)->decrRef();
9714       e->decrRef();
9715     }
9716 }
9717
9718 /*!
9719  * 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).
9720  * 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
9721  * with a plane. The result will be put in 'cut3DSuf' out parameter.
9722  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9723  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9724  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9725  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9726  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9727  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9728  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9729  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9730  * \param [out] cut3DSuf input/output param.
9731  */
9732 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9733                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
9734                                                    const int *desc, const int *descIndx, 
9735                                                    std::vector< std::pair<int,int> >& cut3DSurf)
9736 {
9737   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9738   int nbOf3DSurfCell=(int)cut3DSurf.size();
9739   for(int i=0;i<nbOf3DSurfCell;i++)
9740     {
9741       std::vector<int> res;
9742       int offset=descIndx[i];
9743       int nbOfSeg=descIndx[i+1]-offset;
9744       for(int j=0;j<nbOfSeg;j++)
9745         {
9746           int edgeId=desc[offset+j];
9747           int status=cut3DCurve[edgeId];
9748           if(status!=-2)
9749             {
9750               if(status>-1)
9751                 res.push_back(status);
9752               else
9753                 {
9754                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9755                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9756                 }
9757             }
9758         }
9759       switch(res.size())
9760       {
9761         case 2:
9762           {
9763             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9764             break;
9765           }
9766         case 1:
9767         case 0:
9768           {
9769             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9770             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9771             if(res.size()==2)
9772               {
9773                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9774               }
9775             else
9776               {
9777                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9778               }
9779             break;
9780           }
9781         default:
9782           {// case when plane is on a multi colinear edge of a polyhedron
9783             if((int)res.size()==2*nbOfSeg)
9784               {
9785                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9786               }
9787             else
9788               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9789           }
9790       }
9791     }
9792 }
9793
9794 /*!
9795  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9796  * 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).
9797  * 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
9798  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9799  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9800  * \param desc is the descending connectivity 3D->3DSurf
9801  * \param descIndx is the descending connectivity index 3D->3DSurf
9802  */
9803 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9804                                                   const int *desc, const int *descIndx,
9805                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
9806 {
9807   checkFullyDefined();
9808   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9810   const int *nodal3D=_nodal_connec->getConstPointer();
9811   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9812   int nbOfCells=getNumberOfCells();
9813   for(int i=0;i<nbOfCells;i++)
9814     {
9815       std::map<int, std::set<int> > m;
9816       int offset=descIndx[i];
9817       int nbOfFaces=descIndx[i+1]-offset;
9818       int start=-1;
9819       int end=-1;
9820       for(int j=0;j<nbOfFaces;j++)
9821         {
9822           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9823           if(p.first!=-1 && p.second!=-1)
9824             {
9825               if(p.first!=-2)
9826                 {
9827                   start=p.first; end=p.second;
9828                   m[p.first].insert(p.second);
9829                   m[p.second].insert(p.first);
9830                 }
9831               else
9832                 {
9833                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9834                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9835                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9836                   INTERP_KERNEL::NormalizedCellType cmsId;
9837                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9838                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
9839                   for(unsigned k=0;k<nbOfNodesSon;k++)
9840                     {
9841                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9842                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9843                     }
9844                 }
9845             }
9846         }
9847       if(m.empty())
9848         continue;
9849       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9850       int prev=end;
9851       while(end!=start)
9852         {
9853           std::map<int, std::set<int> >::const_iterator it=m.find(start);
9854           const std::set<int>& s=(*it).second;
9855           std::set<int> s2; s2.insert(prev);
9856           std::set<int> s3;
9857           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9858           if(s3.size()==1)
9859             {
9860               int val=*s3.begin();
9861               conn.push_back(start);
9862               prev=start;
9863               start=val;
9864             }
9865           else
9866             start=end;
9867         }
9868       conn.push_back(end);
9869       if(conn.size()>3)
9870         {
9871           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9872           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9873           cellIds->pushBackSilent(i);
9874         }
9875     }
9876 }
9877
9878 /*!
9879  * 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
9880  * 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
9881  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9882  * 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
9883  * 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.
9884  * 
9885  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9886  */
9887 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9888 {
9889   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9890   if(sz>=4)
9891     {
9892       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9893       if(cm.getDimension()==2)
9894         {
9895           const int *node=nodalConnBg+1;
9896           int startNode=*node++;
9897           double refX=coords[2*startNode];
9898           for(;node!=nodalConnEnd;node++)
9899             {
9900               if(coords[2*(*node)]<refX)
9901                 {
9902                   startNode=*node;
9903                   refX=coords[2*startNode];
9904                 }
9905             }
9906           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9907           refX=1e300;
9908           double tmp1;
9909           double tmp2[2];
9910           double angle0=-M_PI/2;
9911           //
9912           int nextNode=-1;
9913           int prevNode=-1;
9914           double resRef;
9915           double angleNext=0.;
9916           while(nextNode!=startNode)
9917             {
9918               nextNode=-1;
9919               resRef=1e300;
9920               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9921                 {
9922                   if(*node!=tmpOut.back() && *node!=prevNode)
9923                     {
9924                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9925                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9926                       double res;
9927                       if(angleM<=angle0)
9928                         res=angle0-angleM;
9929                       else
9930                         res=angle0-angleM+2.*M_PI;
9931                       if(res<resRef)
9932                         {
9933                           nextNode=*node;
9934                           resRef=res;
9935                           angleNext=angleM;
9936                         }
9937                     }
9938                 }
9939               if(nextNode!=startNode)
9940                 {
9941                   angle0=angleNext-M_PI;
9942                   if(angle0<-M_PI)
9943                     angle0+=2*M_PI;
9944                   prevNode=tmpOut.back();
9945                   tmpOut.push_back(nextNode);
9946                 }
9947             }
9948           std::vector<int> tmp3(2*(sz-1));
9949           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9950           std::copy(nodalConnBg+1,nodalConnEnd,it);
9951           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9952             {
9953               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9954               return false;
9955             }
9956           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9957             {
9958               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9959               return false;
9960             }
9961           else
9962             {
9963               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9964               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9965               return true;
9966             }
9967         }
9968       else
9969         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9970     }
9971   else
9972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9973 }
9974
9975 /*!
9976  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9977  * 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.
9978  * 
9979  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9980  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9981  * \param [in,out] arr array in which the remove operation will be done.
9982  * \param [in,out] arrIndx array in the remove operation will modify
9983  * \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])
9984  * \return true if \b arr and \b arrIndx have been modified, false if not.
9985  */
9986 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9987 {
9988   if(!arrIndx || !arr)
9989     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9990   if(offsetForRemoval<0)
9991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9992   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9993   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9994   int *arrIPtr=arrIndx->getPointer();
9995   *arrIPtr++=0;
9996   int previousArrI=0;
9997   const int *arrPtr=arr->getConstPointer();
9998   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9999   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10000     {
10001       if(*arrIPtr-previousArrI>offsetForRemoval)
10002         {
10003           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10004             {
10005               if(s.find(*work)==s.end())
10006                 arrOut.push_back(*work);
10007             }
10008         }
10009       previousArrI=*arrIPtr;
10010       *arrIPtr=(int)arrOut.size();
10011     }
10012   if(arr->getNumberOfTuples()==(int)arrOut.size())
10013     return false;
10014   arr->alloc((int)arrOut.size(),1);
10015   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10016   return true;
10017 }
10018
10019 /*!
10020  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10021  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10022  * The selection of extraction is done standardly in new2old format.
10023  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10024  *
10025  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10026  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10027  * \param [in] arrIn arr origin array from which the extraction will be done.
10028  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10029  * \param [out] arrOut the resulting array
10030  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10031  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10032  */
10033 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10034                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10035 {
10036   if(!arrIn || !arrIndxIn)
10037     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10038   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10039   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10040     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10041   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10042   const int *arrInPtr=arrIn->getConstPointer();
10043   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10044   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10045   if(nbOfGrps<0)
10046     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10047   int maxSizeOfArr=arrIn->getNumberOfTuples();
10048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10049   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10050   arrIo->alloc((int)(sz+1),1);
10051   const int *idsIt=idsOfSelectBg;
10052   int *work=arrIo->getPointer();
10053   *work++=0;
10054   int lgth=0;
10055   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10056     {
10057       if(*idsIt>=0 && *idsIt<nbOfGrps)
10058         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10059       else
10060         {
10061           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10062           throw INTERP_KERNEL::Exception(oss.str().c_str());
10063         }
10064       if(lgth>=work[-1])
10065         *work=lgth;
10066       else
10067         {
10068           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10069           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10070           throw INTERP_KERNEL::Exception(oss.str().c_str());
10071         }
10072     }
10073   arro->alloc(lgth,1);
10074   work=arro->getPointer();
10075   idsIt=idsOfSelectBg;
10076   for(std::size_t i=0;i<sz;i++,idsIt++)
10077     {
10078       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10079         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10080       else
10081         {
10082           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10083           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10084           throw INTERP_KERNEL::Exception(oss.str().c_str());
10085         }
10086     }
10087   arrOut=arro.retn();
10088   arrIndexOut=arrIo.retn();
10089 }
10090
10091 /*!
10092  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10093  * 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 ).
10094  * The selection of extraction is done standardly in new2old format.
10095  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10096  *
10097  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10098  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10099  * \param [in] arrIn arr origin array from which the extraction will be done.
10100  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10101  * \param [out] arrOut the resulting array
10102  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10103  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10104  */
10105 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10106                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10107 {
10108   if(!arrIn || !arrIndxIn)
10109     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10110   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10111   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10113   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10114   const int *arrInPtr=arrIn->getConstPointer();
10115   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10116   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10117   if(nbOfGrps<0)
10118     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10119   int maxSizeOfArr=arrIn->getNumberOfTuples();
10120   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10122   arrIo->alloc((int)(sz+1),1);
10123   int idsIt=idsOfSelectStart;
10124   int *work=arrIo->getPointer();
10125   *work++=0;
10126   int lgth=0;
10127   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10128     {
10129       if(idsIt>=0 && idsIt<nbOfGrps)
10130         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10131       else
10132         {
10133           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10134           throw INTERP_KERNEL::Exception(oss.str().c_str());
10135         }
10136       if(lgth>=work[-1])
10137         *work=lgth;
10138       else
10139         {
10140           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10141           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10142           throw INTERP_KERNEL::Exception(oss.str().c_str());
10143         }
10144     }
10145   arro->alloc(lgth,1);
10146   work=arro->getPointer();
10147   idsIt=idsOfSelectStart;
10148   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10149     {
10150       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10151         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10152       else
10153         {
10154           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10155           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10156           throw INTERP_KERNEL::Exception(oss.str().c_str());
10157         }
10158     }
10159   arrOut=arro.retn();
10160   arrIndexOut=arrIo.retn();
10161 }
10162
10163 /*!
10164  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10165  * 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
10166  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10167  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10168  *
10169  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10170  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10171  * \param [in] arrIn arr origin array from which the extraction will be done.
10172  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10173  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10174  * \param [in] srcArrIndex index array of \b srcArr
10175  * \param [out] arrOut the resulting array
10176  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10177  * 
10178  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10179  */
10180 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10181                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10182                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10183 {
10184   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10185     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10186   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10188   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10189   std::vector<bool> v(nbOfTuples,true);
10190   int offset=0;
10191   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10192   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10193   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10194     {
10195       if(*it>=0 && *it<nbOfTuples)
10196         {
10197           v[*it]=false;
10198           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10199         }
10200       else
10201         {
10202           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10203           throw INTERP_KERNEL::Exception(oss.str().c_str());
10204         }
10205     }
10206   srcArrIndexPtr=srcArrIndex->getConstPointer();
10207   arrIo->alloc(nbOfTuples+1,1);
10208   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10209   const int *arrInPtr=arrIn->getConstPointer();
10210   const int *srcArrPtr=srcArr->getConstPointer();
10211   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10212   int *arroPtr=arro->getPointer();
10213   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10214     {
10215       if(v[ii])
10216         {
10217           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10218           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10219         }
10220       else
10221         {
10222           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10223           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10224           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10225         }
10226     }
10227   arrOut=arro.retn();
10228   arrIndexOut=arrIo.retn();
10229 }
10230
10231 /*!
10232  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10233  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10234  *
10235  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10236  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10237  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10238  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10239  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10240  * \param [in] srcArrIndex index array of \b srcArr
10241  * 
10242  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10243  */
10244 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10245                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10246 {
10247   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10248     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10249   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10250   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10251   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10252   int *arrInOutPtr=arrInOut->getPointer();
10253   const int *srcArrPtr=srcArr->getConstPointer();
10254   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10255     {
10256       if(*it>=0 && *it<nbOfTuples)
10257         {
10258           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10259             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10260           else
10261             {
10262               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] !";
10263               throw INTERP_KERNEL::Exception(oss.str().c_str());
10264             }
10265         }
10266       else
10267         {
10268           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10269           throw INTERP_KERNEL::Exception(oss.str().c_str());
10270         }
10271     }
10272 }
10273
10274 /*!
10275  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10276  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10277  * 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]].
10278  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10279  * A negative value in \b arrIn means that it is ignored.
10280  * 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.
10281  * 
10282  * \param [in] arrIn arr origin array from which the extraction will be done.
10283  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10284  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10285  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10286  */
10287 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10288 {
10289   int seed=0,nbOfDepthPeelingPerformed=0;
10290   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10291 }
10292
10293 /*!
10294  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10295  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10296  * 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]].
10297  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10298  * A negative value in \b arrIn means that it is ignored.
10299  * 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.
10300  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10301  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10302  * \param [in] arrIn arr origin array from which the extraction will be done.
10303  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10304  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10305  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10306  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10307  * \sa MEDCouplingUMesh::partitionBySpreadZone
10308  */
10309 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10310 {
10311   nbOfDepthPeelingPerformed=0;
10312   if(!arrIndxIn)
10313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10314   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10315   if(nbOfTuples<=0)
10316     {
10317       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10318       return ret;
10319     }
10320   //
10321   std::vector<bool> fetched(nbOfTuples,false);
10322   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10323 }
10324
10325 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10326 {
10327   nbOfDepthPeelingPerformed=0;
10328   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10329     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10330   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10331   std::vector<bool> fetched2(nbOfTuples,false);
10332   int i=0;
10333   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10334     {
10335       if(*seedElt>=0 && *seedElt<nbOfTuples)
10336         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10337       else
10338         { 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()); }
10339     }
10340   const int *arrInPtr=arrIn->getConstPointer();
10341   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10342   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10343   std::vector<int> idsToFetch1(seedBg,seedEnd);
10344   std::vector<int> idsToFetch2;
10345   std::vector<int> *idsToFetch=&idsToFetch1;
10346   std::vector<int> *idsToFetchOther=&idsToFetch2;
10347   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10348     {
10349       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10350         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10351           if(!fetched[*it2])
10352             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10353       std::swap(idsToFetch,idsToFetchOther);
10354       idsToFetchOther->clear();
10355       nbOfDepthPeelingPerformed++;
10356     }
10357   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10358   i=0;
10359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10360   int *retPtr=ret->getPointer();
10361   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10362     if(*it)
10363       *retPtr++=i;
10364   return ret.retn();
10365 }
10366
10367 /*!
10368  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10369  * 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
10370  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10371  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10372  *
10373  * \param [in] start begin of set of ids of the input extraction (included)
10374  * \param [in] end end of set of ids of the input extraction (excluded)
10375  * \param [in] step step of the set of ids in range mode.
10376  * \param [in] arrIn arr origin array from which the extraction will be done.
10377  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10378  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10379  * \param [in] srcArrIndex index array of \b srcArr
10380  * \param [out] arrOut the resulting array
10381  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10382  * 
10383  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10384  */
10385 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10386                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10387                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10388 {
10389   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10390     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10393   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10394   int offset=0;
10395   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10396   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10397   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10398   int it=start;
10399   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10400     {
10401       if(it>=0 && it<nbOfTuples)
10402         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10403       else
10404         {
10405           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10406           throw INTERP_KERNEL::Exception(oss.str().c_str());
10407         }
10408     }
10409   srcArrIndexPtr=srcArrIndex->getConstPointer();
10410   arrIo->alloc(nbOfTuples+1,1);
10411   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10412   const int *arrInPtr=arrIn->getConstPointer();
10413   const int *srcArrPtr=srcArr->getConstPointer();
10414   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10415   int *arroPtr=arro->getPointer();
10416   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10417     {
10418       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10419       if(pos<0)
10420         {
10421           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10422           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10423         }
10424       else
10425         {
10426           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10427           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10428         }
10429     }
10430   arrOut=arro.retn();
10431   arrIndexOut=arrIo.retn();
10432 }
10433
10434 /*!
10435  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10436  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10437  *
10438  * \param [in] start begin of set of ids of the input extraction (included)
10439  * \param [in] end end of set of ids of the input extraction (excluded)
10440  * \param [in] step step of the set of ids in range mode.
10441  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10442  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10443  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10444  * \param [in] srcArrIndex index array of \b srcArr
10445  * 
10446  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10447  */
10448 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10449                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10450 {
10451   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10453   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10454   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10455   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10456   int *arrInOutPtr=arrInOut->getPointer();
10457   const int *srcArrPtr=srcArr->getConstPointer();
10458   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10459   int it=start;
10460   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10461     {
10462       if(it>=0 && it<nbOfTuples)
10463         {
10464           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10465             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10466           else
10467             {
10468               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10469               throw INTERP_KERNEL::Exception(oss.str().c_str());
10470             }
10471         }
10472       else
10473         {
10474           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10475           throw INTERP_KERNEL::Exception(oss.str().c_str());
10476         }
10477     }
10478 }
10479
10480 /*!
10481  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10482  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10483  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10484  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10485  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10486  * 
10487  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10488  */
10489 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10490 {
10491   checkFullyDefined();
10492   int mdim=getMeshDimension();
10493   int spaceDim=getSpaceDimension();
10494   if(mdim!=spaceDim)
10495     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10496   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10497   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10498   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10499   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10500   ret->setCoords(getCoords());
10501   ret->allocateCells((int)partition.size());
10502   //
10503   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10504     {
10505       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10506       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10507       switch(mdim)
10508       {
10509         case 2:
10510           cell=tmp->buildUnionOf2DMesh();
10511           break;
10512         case 3:
10513           cell=tmp->buildUnionOf3DMesh();
10514           break;
10515         default:
10516           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10517       }
10518
10519       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10520     }
10521   //
10522   ret->finishInsertingCells();
10523   return ret.retn();
10524 }
10525
10526 /*!
10527  * This method partitions \b this into contiguous zone.
10528  * This method only needs a well defined connectivity. Coordinates are not considered here.
10529  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10530  */
10531 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10532 {
10533   int nbOfCellsCur=getNumberOfCells();
10534   std::vector<DataArrayInt *> ret;
10535   if(nbOfCellsCur<=0)
10536     return ret;
10537   DataArrayInt *neigh=0,*neighI=0;
10538   computeNeighborsOfCells(neigh,neighI);
10539   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10540   std::vector<bool> fetchedCells(nbOfCellsCur,false);
10541   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10542   int seed=0;
10543   while(seed<nbOfCellsCur)
10544     {
10545       int nbOfPeelPerformed=0;
10546       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10547       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10548     }
10549   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10550     ret.push_back((*it).retn());
10551   return ret;
10552 }
10553
10554 /*!
10555  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10556  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10557  *
10558  * \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.
10559  * \return a newly allocated DataArrayInt to be managed by the caller.
10560  * \throw In case of \a code has not the right format (typically of size 3*n)
10561  */
10562 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10563 {
10564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10565   std::size_t nb=code.size()/3;
10566   if(code.size()%3!=0)
10567     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10568   ret->alloc((int)nb,2);
10569   int *retPtr=ret->getPointer();
10570   for(std::size_t i=0;i<nb;i++,retPtr+=2)
10571     {
10572       retPtr[0]=code[3*i+2];
10573       retPtr[1]=code[3*i+2]+code[3*i+1];
10574     }
10575   return ret.retn();
10576 }
10577
10578 /*!
10579  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10580  * All cells in \a this are expected to be linear 3D cells.
10581  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10582  * It leads to an increase to number of cells.
10583  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10584  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
10585  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10586  *
10587  * \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.
10588  *                      For all other cells, the splitting policy will be ignored.
10589  * \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. 
10590  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10591  *          an id of old cell producing it. The caller is to delete this array using
10592  *         decrRef() as it is no more needed.
10593  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10594  *
10595  * \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
10596  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10597  * 
10598  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10599  * \throw If \a this is not fully constituted with linear 3D cells.
10600  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10601  */
10602 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10603 {
10604   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10605   checkConnectivityFullyDefined();
10606   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10607     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10608   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10609   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10610   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10611   int *retPt(ret->getPointer());
10612   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10613   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10614   const int *oldc(_nodal_connec->begin());
10615   const int *oldci(_nodal_connec_index->begin());
10616   const double *coords(_coords->begin());
10617   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10618     {
10619       std::vector<int> a; std::vector<double> b;
10620       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10621       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10622       const int *aa(&a[0]);
10623       if(!b.empty())
10624         {
10625           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10626             if(*it<0)
10627               *it=(-(*(it))-1+nbNodes);
10628           addPts->insertAtTheEnd(b.begin(),b.end());
10629           nbNodes+=(int)b.size()/3;
10630         }
10631       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10632         newConn->insertAtTheEnd(aa,aa+4);
10633     }
10634   if(!addPts->empty())
10635     {
10636       addPts->rearrange(3);
10637       nbOfAdditionalPoints=addPts->getNumberOfTuples();
10638       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
10639       ret0->setCoords(addPts);
10640     }
10641   else
10642     {
10643       nbOfAdditionalPoints=0;
10644       ret0->setCoords(getCoords());
10645     }
10646   ret0->setNodalConnectivity(newConn);
10647   //
10648   ret->computeOffsets2();
10649   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10650   return ret0.retn();
10651 }
10652
10653 /*!
10654  * 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). 
10655  *
10656  * \sa MEDCouplingUMesh::split2DCells
10657  */
10658 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10659 {
10660   checkConnectivityFullyDefined();
10661   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10662   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10663   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10664   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10665   int prevPosOfCi(ciPtr[0]);
10666   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10667     {
10668       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10669       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10670       for(int j=0;j<sz;j++)
10671         {
10672           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10673           for(int k=0;k<sz2;k++)
10674             *cPtr++=subPtr[offset2+k];
10675           if(j!=sz-1)
10676             *cPtr++=oldConn[prevPosOfCi+j+2];
10677           deltaSz+=sz2;
10678         }
10679       prevPosOfCi=ciPtr[1];
10680       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10681     }
10682   if(c->end()!=cPtr)
10683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10684   _nodal_connec->decrRef();
10685   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10686 }
10687
10688 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10689 {
10690   if(id!=-1)
10691     return id;
10692   else
10693     {
10694       int ret(nodesCnter++);
10695       double newPt[2];
10696       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10697       addCoo.insertAtTheEnd(newPt,newPt+2);
10698       return ret;
10699     }
10700 }
10701
10702 /// @cond INTERNAL
10703
10704 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)
10705 {
10706   int tmp[3];
10707   int trueStart(start>=0?start:nbOfEdges+start);
10708   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
10709   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
10710   if(linOrArc)
10711     {
10712       if(stp-start>1)
10713         {
10714           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10715           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
10716           middles.push_back(tmp3+offset);
10717         }
10718       else
10719         middles.push_back(connBg[trueStart+nbOfEdges]);
10720     }
10721 }
10722
10723 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)
10724 {
10725   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
10726   newConnOfCell->pushBackSilent(tmpEnd);
10727   if(linOrArc)
10728     {
10729       if(stp-start>1)
10730         {
10731           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10732           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10733           middles.push_back(tmp3+offset);
10734         }
10735       else
10736         middles.push_back(connBg[start+nbOfEdges]);
10737     }
10738 }
10739
10740 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)
10741 {
10742   if(linOrArc)
10743     {
10744       if(stp-start>1)
10745         {
10746           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
10747           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10748           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10749           middles.push_back(tmp3+offset);
10750         }
10751       else
10752         middles.push_back(connBg[start+nbOfEdges]);
10753     }
10754 }
10755
10756 /// @cond INTERNAL
10757
10758 /*!
10759  * 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 ) .
10760  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
10761  */
10762 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
10763 {
10764   std::size_t sz(std::distance(connBg,connEnd));
10765   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
10766     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
10767   sz--;
10768   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
10769   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
10770   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
10771   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
10772   INTERP_KERNEL::NormalizedCellType typeOfSon;
10773   std::vector<int> middles;
10774   bool ret(false);
10775   for(;nbOfHit<nbs;nbOfTurn++)
10776     {
10777       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
10778       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10779       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10780       posEndElt++;
10781       nbOfHit++;
10782       unsigned endI(nbs-nbOfHit);
10783       for(unsigned i=0;i<endI;i++)
10784         {
10785           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
10786           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10787           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
10788           bool isColinear(eint->areColinears());
10789           if(isColinear)
10790             {
10791               nbOfHit++;
10792               posEndElt++;
10793               ret=true;
10794             }
10795           delete eint;
10796           eCand->decrRef();
10797           if(!isColinear)
10798             {
10799               if(nbOfTurn==0)
10800                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
10801                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
10802                   for(unsigned ii=0;ii<endII;ii++)
10803                     {
10804                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
10805                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
10806                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
10807                       isColinear=eint->areColinears();
10808                       if(isColinear)
10809                         {
10810                           nbOfHit++;
10811                           posBaseElt--;
10812                           ret=true;
10813                         }
10814                       delete eint;
10815                       eCand->decrRef();
10816                       if(!isColinear)
10817                         break;
10818                     }
10819                 }
10820               break;
10821             }
10822         }
10823       //push [posBaseElt,posEndElt) in newConnOfCell using e
10824       if(nbOfTurn==0)
10825         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10826       else if(nbOfHit!=nbs)
10827         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10828       else
10829         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10830       posBaseElt=posEndElt;
10831       e->decrRef();
10832     }
10833   if(!middles.empty())
10834     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
10835   return ret;
10836 }
10837
10838 /*!
10839  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10840  *
10841  * \return  int - the number of new nodes created.
10842  * \sa MEDCouplingUMesh::split2DCells
10843  */
10844 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10845 {
10846   checkCoherency();
10847   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10849   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10850   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10851   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10852   const double *oldCoordsPtr(getCoords()->begin());
10853   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10854   int prevPosOfCi(ciPtr[0]);
10855   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10856     {
10857       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10858       for(int j=0;j<sz;j++)
10859         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10860       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10861       for(int j=0;j<sz;j++)//loop over subedges of oldConn
10862         {
10863           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10864           if(sz2==0)
10865             {
10866               if(j<sz-1)
10867                 cPtr[1]=oldConn[prevPosOfCi+2+j];
10868               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10869               continue;
10870             }
10871           std::vector<INTERP_KERNEL::Node *> ns(3);
10872           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10873           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10874           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10875           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10876           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10877             {
10878               cPtr[1]=subPtr[offset2+k];
10879               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10880             }
10881           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10882           if(j!=sz-1)
10883             { cPtr[1]=tmpEnd; }
10884           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10885         }
10886       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10887       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10888     }
10889   if(c->end()!=cPtr)
10890     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10891   _nodal_connec->decrRef();
10892   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10893   addCoo->rearrange(2);
10894   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10895   setCoords(coo);
10896   return addCoo->getNumberOfTuples();
10897 }
10898
10899 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10900     _own_cell(true),_cell_id(-1),_nb_cell(0)
10901 {
10902   if(mesh)
10903     {
10904       mesh->incrRef();
10905       _nb_cell=mesh->getNumberOfCells();
10906     }
10907 }
10908
10909 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10910 {
10911   if(_mesh)
10912     _mesh->decrRef();
10913   if(_own_cell)
10914     delete _cell;
10915 }
10916
10917 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10918     _own_cell(false),_cell_id(bg-1),
10919     _nb_cell(end)
10920 {
10921   if(mesh)
10922     mesh->incrRef();
10923 }
10924
10925 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10926 {
10927   _cell_id++;
10928   if(_cell_id<_nb_cell)
10929     {
10930       _cell->next();
10931       return _cell;
10932     }
10933   else
10934     return 0;
10935 }
10936
10937 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10938 {
10939   if(_mesh)
10940     _mesh->incrRef();
10941 }
10942
10943 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10944 {
10945   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10946 }
10947
10948 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10949 {
10950   if(_mesh)
10951     _mesh->decrRef();
10952 }
10953
10954 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10955     _itc(itc),
10956     _bg(bg),_end(end)
10957 {
10958   if(_mesh)
10959     _mesh->incrRef();
10960 }
10961
10962 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10963 {
10964   if(_mesh)
10965     _mesh->decrRef();
10966 }
10967
10968 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10969 {
10970   return _type;
10971 }
10972
10973 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10974 {
10975   return _end-_bg;
10976 }
10977
10978 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10979 {
10980   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10981 }
10982
10983 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10984 {
10985   if(mesh)
10986     {
10987       mesh->incrRef();
10988       _nb_cell=mesh->getNumberOfCells();
10989     }
10990 }
10991
10992 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10993 {
10994   if(_mesh)
10995     _mesh->decrRef();
10996   delete _cell;
10997 }
10998
10999 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11000 {
11001   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11002   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11003   if(_cell_id<_nb_cell)
11004     {
11005       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11006       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11007       int startId=_cell_id;
11008       _cell_id+=nbOfElems;
11009       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11010     }
11011   else
11012     return 0;
11013 }
11014
11015 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11016 {
11017   if(mesh)
11018     {
11019       _conn=mesh->getNodalConnectivity()->getPointer();
11020       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11021     }
11022 }
11023
11024 void MEDCouplingUMeshCell::next()
11025 {
11026   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11027     {
11028       _conn+=_conn_lgth;
11029       _conn_indx++;
11030     }
11031   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11032 }
11033
11034 std::string MEDCouplingUMeshCell::repr() const
11035 {
11036   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11037     {
11038       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11039       oss << " : ";
11040       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11041       return oss.str();
11042     }
11043   else
11044     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11045 }
11046
11047 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11048 {
11049   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11050     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11051   else
11052     return INTERP_KERNEL::NORM_ERROR;
11053 }
11054
11055 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11056 {
11057   lgth=_conn_lgth;
11058   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11059     return _conn;
11060   else
11061     return 0;
11062 }