Salome HOME
Implementation of MEDCouplingPointSet.computeDiameterField (EDF10718)
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  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 "DiameterCalculator.hxx"
33 #include "DirectedBoundingBox.hxx"
34 #include "InterpKernelMatrixTools.hxx"
35 #include "InterpKernelMeshQuality.hxx"
36 #include "InterpKernelCellSimplify.hxx"
37 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
38 #include "InterpKernelAutoPtr.hxx"
39 #include "InterpKernelGeo2DNode.hxx"
40 #include "InterpKernelGeo2DEdgeLin.hxx"
41 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
42 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
43
44 #include <sstream>
45 #include <fstream>
46 #include <numeric>
47 #include <cstring>
48 #include <limits>
49 #include <list>
50
51 using namespace ParaMEDMEM;
52
53 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
54
55 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 };
56
57 MEDCouplingUMesh *MEDCouplingUMesh::New()
58 {
59   return new MEDCouplingUMesh;
60 }
61
62 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
63 {
64   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
65   ret->setName(meshName);
66   ret->setMeshDimension(meshDim);
67   return ret;
68 }
69
70 /*!
71  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
72  * between \a this and the new mesh.
73  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
74  *          delete this mesh using decrRef() as it is no more needed. 
75  */
76 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
77 {
78   return clone(true);
79 }
80
81 /*!
82  * Returns a new MEDCouplingMesh which is a copy of \a this one.
83  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
84  * this mesh are shared by the new mesh.
85  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
86  *          delete this mesh using decrRef() as it is no more needed. 
87  */
88 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
89 {
90   return new MEDCouplingUMesh(*this,recDeepCpy);
91 }
92
93 /*!
94  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
95  * The coordinates are shared between \a this and the returned instance.
96  * 
97  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
98  * \sa MEDCouplingUMesh::deepCpy
99  */
100 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
101 {
102   checkConnectivityFullyDefined();
103   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
105   ret->setConnectivity(c,ci);
106   return ret.retn();
107 }
108
109 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
110 {
111   if(!other)
112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
113   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
114   if(!otherC)
115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
116   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
117   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
118 }
119
120 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
121 {
122   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
123   return ret;
124 }
125
126 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
127 {
128   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
129   ret.push_back(_nodal_connec);
130   ret.push_back(_nodal_connec_index);
131   return ret;
132 }
133
134 void MEDCouplingUMesh::updateTime() const
135 {
136   MEDCouplingPointSet::updateTime();
137   if(_nodal_connec)
138     {
139       updateTimeWith(*_nodal_connec);
140     }
141   if(_nodal_connec_index)
142     {
143       updateTimeWith(*_nodal_connec_index);
144     }
145 }
146
147 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
148 {
149 }
150
151 /*!
152  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
153  * then \a this mesh is most probably is writable, exchangeable and available for most
154  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
155  * this method to check that all is in order with \a this mesh.
156  *  \throw If the mesh dimension is not set.
157  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
158  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
159  *  \throw If the connectivity data array has more than one component.
160  *  \throw If the connectivity data array has a named component.
161  *  \throw If the connectivity index data array has more than one component.
162  *  \throw If the connectivity index data array has a named component.
163  */
164 void MEDCouplingUMesh::checkCoherency() const
165 {
166   if(_mesh_dim<-1)
167     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
168   if(_mesh_dim!=-1)
169     MEDCouplingPointSet::checkCoherency();
170   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
171     {
172       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
173         {
174           std::ostringstream message;
175           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
176           throw INTERP_KERNEL::Exception(message.str().c_str());
177         }
178     }
179   if(_nodal_connec)
180     {
181       if(_nodal_connec->getNumberOfComponents()!=1)
182         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
183       if(_nodal_connec->getInfoOnComponent(0)!="")
184         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
185     }
186   else
187     if(_mesh_dim!=-1)
188       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
189   if(_nodal_connec_index)
190     {
191       if(_nodal_connec_index->getNumberOfComponents()!=1)
192         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
193       if(_nodal_connec_index->getInfoOnComponent(0)!="")
194         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
195     }
196   else
197     if(_mesh_dim!=-1)
198       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
199 }
200
201 /*!
202  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
203  * then \a this mesh is most probably is writable, exchangeable and available for all
204  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
205  * method thoroughly checks the nodal connectivity.
206  *  \param [in] eps - a not used parameter.
207  *  \throw If the mesh dimension is not set.
208  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
209  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
210  *  \throw If the connectivity data array has more than one component.
211  *  \throw If the connectivity data array has a named component.
212  *  \throw If the connectivity index data array has more than one component.
213  *  \throw If the connectivity index data array has a named component.
214  *  \throw If number of nodes defining an element does not correspond to the type of element.
215  *  \throw If the nodal connectivity includes an invalid node id.
216  */
217 void MEDCouplingUMesh::checkCoherency1(double eps) const
218 {
219   checkCoherency();
220   if(_mesh_dim==-1)
221     return ;
222   int meshDim=getMeshDimension();
223   int nbOfNodes=getNumberOfNodes();
224   int nbOfCells=getNumberOfCells();
225   const int *ptr=_nodal_connec->getConstPointer();
226   const int *ptrI=_nodal_connec_index->getConstPointer();
227   for(int i=0;i<nbOfCells;i++)
228     {
229       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
230       if((int)cm.getDimension()!=meshDim)
231         {
232           std::ostringstream oss;
233           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
234           throw INTERP_KERNEL::Exception(oss.str().c_str());
235         }
236       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
237       if(!cm.isDynamic())
238         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
239           {
240             std::ostringstream oss;
241             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
242             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
243             throw INTERP_KERNEL::Exception(oss.str().c_str());
244           }
245       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
246         {
247           int nodeId=*w;
248           if(nodeId>=0)
249             {
250               if(nodeId>=nbOfNodes)
251                 {
252                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
253                   throw INTERP_KERNEL::Exception(oss.str().c_str());
254                 }
255             }
256           else if(nodeId<-1)
257             {
258               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
259               throw INTERP_KERNEL::Exception(oss.str().c_str());
260             }
261           else
262             {
263               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
264                 {
265                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
266                   throw INTERP_KERNEL::Exception(oss.str().c_str());
267                 }
268             }
269         }
270     }
271 }
272
273
274 /*!
275  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
276  * then \a this mesh is most probably is writable, exchangeable and available for all
277  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
278  *  \param [in] eps - a not used parameter.
279  *  \throw If the mesh dimension is not set.
280  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
281  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
282  *  \throw If the connectivity data array has more than one component.
283  *  \throw If the connectivity data array has a named component.
284  *  \throw If the connectivity index data array has more than one component.
285  *  \throw If the connectivity index data array has a named component.
286  *  \throw If number of nodes defining an element does not correspond to the type of element.
287  *  \throw If the nodal connectivity includes an invalid node id.
288  */
289 void MEDCouplingUMesh::checkCoherency2(double eps) const
290 {
291   checkCoherency1(eps);
292 }
293
294 /*!
295  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
296  * elements contained in the mesh. For more info on the mesh dimension see
297  * \ref MEDCouplingUMeshPage.
298  *  \param [in] meshDim - a new mesh dimension.
299  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
300  */
301 void MEDCouplingUMesh::setMeshDimension(int meshDim)
302 {
303   if(meshDim<-1 || meshDim>3)
304     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
305   _mesh_dim=meshDim;
306   declareAsNew();
307 }
308
309 /*!
310  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
311  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
312  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
313  *
314  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
315  *
316  *  \if ENABLE_EXAMPLES
317  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
318  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
319  *  \endif
320  */
321 void MEDCouplingUMesh::allocateCells(int nbOfCells)
322 {
323   if(nbOfCells<0)
324     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
325   if(_nodal_connec_index)
326     {
327       _nodal_connec_index->decrRef();
328     }
329   if(_nodal_connec)
330     {
331       _nodal_connec->decrRef();
332     }
333   _nodal_connec_index=DataArrayInt::New();
334   _nodal_connec_index->reserve(nbOfCells+1);
335   _nodal_connec_index->pushBackSilent(0);
336   _nodal_connec=DataArrayInt::New();
337   _nodal_connec->reserve(2*nbOfCells);
338   _types.clear();
339   declareAsNew();
340 }
341
342 /*!
343  * Appends a cell to the connectivity array. For deeper understanding what is
344  * happening see \ref MEDCouplingUMeshNodalConnectivity.
345  *  \param [in] type - type of cell to add.
346  *  \param [in] size - number of nodes constituting this cell.
347  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
348  * 
349  *  \if ENABLE_EXAMPLES
350  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
351  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
352  *  \endif
353  */
354 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
355 {
356   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
357   if(_nodal_connec_index==0)
358     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
359   if((int)cm.getDimension()==_mesh_dim)
360     {
361       if(!cm.isDynamic())
362         if(size!=(int)cm.getNumberOfNodes())
363           {
364             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
365             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
366             throw INTERP_KERNEL::Exception(oss.str().c_str());
367           }
368       int idx=_nodal_connec_index->back();
369       int val=idx+size+1;
370       _nodal_connec_index->pushBackSilent(val);
371       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
372       _types.insert(type);
373     }
374   else
375     {
376       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
377       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
378       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
379       throw INTERP_KERNEL::Exception(oss.str().c_str());
380     }
381 }
382
383 /*!
384  * Compacts data arrays to release unused memory. This method is to be called after
385  * finishing cell insertion using \a this->insertNextCell().
386  * 
387  *  \if ENABLE_EXAMPLES
388  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
389  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
390  *  \endif
391  */
392 void MEDCouplingUMesh::finishInsertingCells()
393 {
394   _nodal_connec->pack();
395   _nodal_connec_index->pack();
396   _nodal_connec->declareAsNew();
397   _nodal_connec_index->declareAsNew();
398   updateTime();
399 }
400
401 /*!
402  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
403  * Useful for python users.
404  */
405 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
406 {
407   return new MEDCouplingUMeshCellIterator(this);
408 }
409
410 /*!
411  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
412  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
413  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
414  * Useful for python users.
415  */
416 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
417 {
418   if(!checkConsecutiveCellTypes())
419     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
420   return new MEDCouplingUMeshCellByTypeEntry(this);
421 }
422
423 /*!
424  * Returns a set of all cell types available in \a this mesh.
425  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
426  * \warning this method does not throw any exception even if \a this is not defined.
427  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
428  */
429 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
430 {
431   return _types;
432 }
433
434 /*!
435  * This method returns the sorted list of geometric types in \a this.
436  * 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
437  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
438  *
439  * \throw if connectivity in \a this is not correctly defined.
440  *  
441  * \sa MEDCouplingMesh::getAllGeoTypes
442  */
443 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
444 {
445   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
446   checkConnectivityFullyDefined();
447   int nbOfCells(getNumberOfCells());
448   if(nbOfCells==0)
449     return ret;
450   if(getMeshLength()<1)
451     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
452   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
453   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
454   for(int i=1;i<nbOfCells;i++,ci++)
455     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
456       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
457   return ret;
458 }
459
460 /*!
461  * This method is a method that compares \a this and \a other.
462  * This method compares \b all attributes, even names and component names.
463  */
464 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
465 {
466   if(!other)
467     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
468   std::ostringstream oss; oss.precision(15);
469   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
470   if(!otherC)
471     {
472       reason="mesh given in input is not castable in MEDCouplingUMesh !";
473       return false;
474     }
475   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
476     return false;
477   if(_mesh_dim!=otherC->_mesh_dim)
478     {
479       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
480       reason=oss.str();
481       return false;
482     }
483   if(_types!=otherC->_types)
484     {
485       oss << "umesh geometric type mismatch :\nThis geometric types are :";
486       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
487         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
488       oss << "\nOther geometric types are :";
489       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
490         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
491       reason=oss.str();
492       return false;
493     }
494   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
495     if(_nodal_connec==0 || otherC->_nodal_connec==0)
496       {
497         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
498         return false;
499       }
500   if(_nodal_connec!=otherC->_nodal_connec)
501     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
502       {
503         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
504         return false;
505       }
506   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
507     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
508       {
509         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
510         return false;
511       }
512   if(_nodal_connec_index!=otherC->_nodal_connec_index)
513     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
514       {
515         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
516         return false;
517       }
518   return true;
519 }
520
521 /*!
522  * Checks if data arrays of this mesh (node coordinates, nodal
523  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
524  * not considered.
525  *  \param [in] other - the mesh to compare with.
526  *  \param [in] prec - precision value used to compare node coordinates.
527  *  \return bool - \a true if the two meshes are same.
528  */
529 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
530 {
531   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
532   if(!otherC)
533     return false;
534   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
535     return false;
536   if(_mesh_dim!=otherC->_mesh_dim)
537     return false;
538   if(_types!=otherC->_types)
539     return false;
540   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
541     if(_nodal_connec==0 || otherC->_nodal_connec==0)
542       return false;
543   if(_nodal_connec!=otherC->_nodal_connec)
544     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
545       return false;
546   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
547     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
548       return false;
549   if(_nodal_connec_index!=otherC->_nodal_connec_index)
550     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
551       return false;
552   return true;
553 }
554
555 /*!
556  * Checks if \a this and \a other meshes are geometrically equivalent with high
557  * probability, else an exception is thrown. The meshes are considered equivalent if
558  * (1) meshes contain the same number of nodes and the same number of elements of the
559  * same types (2) three cells of the two meshes (first, last and middle) are based
560  * on coincident nodes (with a specified precision).
561  *  \param [in] other - the mesh to compare with.
562  *  \param [in] prec - the precision used to compare nodes of the two meshes.
563  *  \throw If the two meshes do not match.
564  */
565 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
566 {
567   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
568   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
569   if(!otherC)
570     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
571 }
572
573 /*!
574  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
575  * cells each node belongs to.
576  * \warning For speed reasons, this method does not check if node ids in the nodal
577  *          connectivity correspond to the size of node coordinates array.
578  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
579  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
580  *        dividing cell ids in \a revNodal into groups each referring to one
581  *        node. Its every element (except the last one) is an index pointing to the
582  *         first id of a group of cells. For example cells sharing the node #1 are 
583  *        described by following range of indices: 
584  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
585  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
586  *        Number of cells sharing the *i*-th node is
587  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
588  * \throw If the coordinates array is not set.
589  * \throw If the nodal connectivity of cells is not defined.
590  * 
591  * \if ENABLE_EXAMPLES
592  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
593  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
594  * \endif
595  */
596 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
597 {
598   checkFullyDefined();
599   int nbOfNodes=getNumberOfNodes();
600   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
601   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
602   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
603   const int *conn=_nodal_connec->getConstPointer();
604   const int *connIndex=_nodal_connec_index->getConstPointer();
605   int nbOfCells=getNumberOfCells();
606   int nbOfEltsInRevNodal=0;
607   for(int eltId=0;eltId<nbOfCells;eltId++)
608     {
609       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
610       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
611       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
612         if(*iter>=0)//for polyhedrons
613           {
614             nbOfEltsInRevNodal++;
615             revNodalIndxPtr[(*iter)+1]++;
616           }
617     }
618   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
619   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
620   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
621   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
622   for(int eltId=0;eltId<nbOfCells;eltId++)
623     {
624       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
625       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
626       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
627         if(*iter>=0)//for polyhedrons
628           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
629     }
630 }
631
632 /// @cond INTERNAL
633
634 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
635 {
636   return id;
637 }
638
639 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
640 {
641   if(!compute)
642     return id+1;
643   else
644     {
645       if(cm.getOrientationStatus(nb,conn1,conn2))
646         return id+1;
647       else
648         return -(id+1);
649     }
650 }
651
652 class MinusOneSonsGenerator
653 {
654 public:
655   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
656   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
657   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
658   static const int DELTA=1;
659 private:
660   const INTERP_KERNEL::CellModel& _cm;
661 };
662
663 class MinusOneSonsGeneratorBiQuadratic
664 {
665 public:
666   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
667   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
668   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
669   static const int DELTA=1;
670 private:
671   const INTERP_KERNEL::CellModel& _cm;
672 };
673
674 class MinusTwoSonsGenerator
675 {
676 public:
677   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
678   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
679   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
680   static const int DELTA=2;
681 private:
682   const INTERP_KERNEL::CellModel& _cm;
683 };
684
685 /// @endcond
686
687 /*!
688  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
689  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
690  * describing correspondence between cells of \a this and the result meshes are
691  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
692  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
693  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
694  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
695  * \warning For speed reasons, this method does not check if node ids in the nodal
696  *          connectivity correspond to the size of node coordinates array.
697  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
698  *          to write this mesh to the MED file, its cells must be sorted using
699  *          sortCellsInMEDFileFrmt().
700  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
701  *         each cell of \a this mesh.
702  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
703  *        dividing cell ids in \a desc into groups each referring to one
704  *        cell of \a this mesh. Its every element (except the last one) is an index
705  *        pointing to the first id of a group of cells. For example cells of the
706  *        result mesh bounding the cell #1 of \a this mesh are described by following
707  *        range of indices:
708  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
709  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
710  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
711  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
712  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
713  *         by each cell of the result mesh.
714  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
715  *        in the result mesh,
716  *        dividing cell ids in \a revDesc into groups each referring to one
717  *        cell of the result mesh the same way as \a descIndx divides \a desc.
718  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
719  *        delete this mesh using decrRef() as it is no more needed.
720  *  \throw If the coordinates array is not set.
721  *  \throw If the nodal connectivity of cells is node defined.
722  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
723  *         revDescIndx == NULL.
724  * 
725  *  \if ENABLE_EXAMPLES
726  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
727  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
728  *  \endif
729  * \sa buildDescendingConnectivity2()
730  */
731 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
732 {
733   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
734 }
735
736 /*!
737  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
738  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
739  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
740  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
741  * \sa MEDCouplingUMesh::buildDescendingConnectivity
742  */
743 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
744 {
745   checkFullyDefined();
746   if(getMeshDimension()!=3)
747     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
748   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
749 }
750
751 /*!
752  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
753  * this->getMeshDimension(), that bound cells of \a this mesh. In
754  * addition arrays describing correspondence between cells of \a this and the result
755  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
756  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
757  *  mesh. This method differs from buildDescendingConnectivity() in that apart
758  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
759  * result meshes. So a positive id means that order of nodes in corresponding cells
760  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
761  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
762  * i.e. cell ids are one-based.
763  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
764  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
765  * \warning For speed reasons, this method does not check if node ids in the nodal
766  *          connectivity correspond to the size of node coordinates array.
767  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
768  *          to write this mesh to the MED file, its cells must be sorted using
769  *          sortCellsInMEDFileFrmt().
770  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
771  *         each cell of \a this mesh.
772  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
773  *        dividing cell ids in \a desc into groups each referring to one
774  *        cell of \a this mesh. Its every element (except the last one) is an index
775  *        pointing to the first id of a group of cells. For example cells of the
776  *        result mesh bounding the cell #1 of \a this mesh are described by following
777  *        range of indices:
778  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
779  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
780  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
781  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
782  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
783  *         by each cell of the result mesh.
784  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
785  *        in the result mesh,
786  *        dividing cell ids in \a revDesc into groups each referring to one
787  *        cell of the result mesh the same way as \a descIndx divides \a desc.
788  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
789  *        shares the node coordinates array with \a this mesh. The caller is to
790  *        delete this mesh using decrRef() as it is no more needed.
791  *  \throw If the coordinates array is not set.
792  *  \throw If the nodal connectivity of cells is node defined.
793  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
794  *         revDescIndx == NULL.
795  * 
796  *  \if ENABLE_EXAMPLES
797  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
798  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
799  *  \endif
800  * \sa buildDescendingConnectivity()
801  */
802 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
803 {
804   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
805 }
806
807 /*!
808  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
809  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
810  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
811  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
812  *
813  * \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
814  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
815  * \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.
816  */
817 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
818 {
819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
823   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
824   meshDM1=0;
825   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
826 }
827
828 /*!
829  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
830  * 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,
831  * excluding a set of meshdim-1 cells in input descending connectivity.
832  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
833  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
834  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
835  *
836  * \param [in] desc descending connectivity array.
837  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
838  * \param [in] revDesc reverse descending connectivity array.
839  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
840  * \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
841  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
842  * \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.
843  */
844 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
845                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
846 {
847   if(!desc || !descIndx || !revDesc || !revDescIndx)
848     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
849   const int *descPtr=desc->getConstPointer();
850   const int *descIPtr=descIndx->getConstPointer();
851   const int *revDescPtr=revDesc->getConstPointer();
852   const int *revDescIPtr=revDescIndx->getConstPointer();
853   //
854   int nbCells=descIndx->getNumberOfTuples()-1;
855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
857   int *out1Ptr=out1->getPointer();
858   *out1Ptr++=0;
859   out0->reserve(desc->getNumberOfTuples());
860   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
861     {
862       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
863         {
864           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
865           s.erase(i);
866           out0->insertAtTheEnd(s.begin(),s.end());
867         }
868       *out1Ptr=out0->getNumberOfTuples();
869     }
870   neighbors=out0.retn();
871   neighborsIndx=out1.retn();
872 }
873
874 /*!
875  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
876  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
877  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
878  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
879  *
880  * \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
881  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
882  * \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.
883  */
884 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
885 {
886   checkFullyDefined();
887   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
888   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
889   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
890   switch(mdim)
891   {
892     case 3:
893       {
894         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
895         break;
896       }
897     case 2:
898       {
899         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
900         break;
901       }
902     case 1:
903       {
904         mesh1D=const_cast<MEDCouplingUMesh *>(this);
905         mesh1D->incrRef();
906         break;
907       }
908     default:
909       {
910         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
911       }
912   }
913   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
914   mesh1D->getReverseNodalConnectivity(desc,descIndx);
915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
916   ret0->alloc(desc->getNumberOfTuples(),1);
917   int *r0Pt(ret0->getPointer());
918   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
919   for(int i=0;i<nbNodes;i++,rni++)
920     {
921       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
922         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
923     }
924   neighbors=ret0.retn();
925   neighborsIdx=descIndx.retn();
926 }
927
928 /// @cond INTERNAL
929
930 /*!
931  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
932  * For speed reasons no check of this will be done.
933  */
934 template<class SonsGenerator>
935 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
936 {
937   if(!desc || !descIndx || !revDesc || !revDescIndx)
938     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
939   checkConnectivityFullyDefined();
940   int nbOfCells=getNumberOfCells();
941   int nbOfNodes=getNumberOfNodes();
942   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
943   int *revNodalIndxPtr=revNodalIndx->getPointer();
944   const int *conn=_nodal_connec->getConstPointer();
945   const int *connIndex=_nodal_connec_index->getConstPointer();
946   std::string name="Mesh constituent of "; name+=getName();
947   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
948   ret->setCoords(getCoords());
949   ret->allocateCells(2*nbOfCells);
950   descIndx->alloc(nbOfCells+1,1);
951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
952   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
953   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
954     {
955       int pos=connIndex[eltId];
956       int posP1=connIndex[eltId+1];
957       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
958       SonsGenerator sg(cm);
959       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
960       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
961       for(unsigned i=0;i<nbOfSons;i++)
962         {
963           INTERP_KERNEL::NormalizedCellType cmsId;
964           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
965           for(unsigned k=0;k<nbOfNodesSon;k++)
966             if(tmp[k]>=0)
967               revNodalIndxPtr[tmp[k]+1]++;
968           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
969           revDesc2->pushBackSilent(eltId);
970         }
971       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
972     }
973   int nbOfCellsM1=ret->getNumberOfCells();
974   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
976   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
977   int *revNodalPtr=revNodal->getPointer();
978   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
979   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
980   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
981     {
982       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
983       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
984       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
985         if(*iter>=0)//for polyhedrons
986           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
987     }
988   //
989   DataArrayInt *commonCells=0,*commonCellsI=0;
990   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
991   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
992   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
993   int newNbOfCellsM1=-1;
994   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
995                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
996   std::vector<bool> isImpacted(nbOfCellsM1,false);
997   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
998     for(int work2=work[0];work2!=work[1];work2++)
999       isImpacted[commonCellsPtr[work2]]=true;
1000   const int *o2nM1Ptr=o2nM1->getConstPointer();
1001   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1002   const int *n2oM1Ptr=n2oM1->getConstPointer();
1003   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1004   ret2->copyTinyInfoFrom(this);
1005   desc->alloc(descIndx->back(),1);
1006   int *descPtr=desc->getPointer();
1007   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1008   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1009     {
1010       if(!isImpacted[i])
1011         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1012       else
1013         {
1014           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1015             {
1016               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1017               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1018             }
1019           else
1020             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1021         }
1022     }
1023   revDesc->reserve(newNbOfCellsM1);
1024   revDescIndx->alloc(newNbOfCellsM1+1,1);
1025   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1026   const int *revDesc2Ptr=revDesc2->getConstPointer();
1027   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1028     {
1029       int oldCellIdM1=n2oM1Ptr[i];
1030       if(!isImpacted[oldCellIdM1])
1031         {
1032           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1033           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1034         }
1035       else
1036         {
1037           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1038             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1039           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1040           commonCellsIPtr++;
1041         }
1042     }
1043   //
1044   return ret2.retn();
1045 }
1046
1047 struct MEDCouplingAccVisit
1048 {
1049   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1050   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1051   int _new_nb_of_nodes;
1052 };
1053
1054 /// @endcond
1055
1056 /*!
1057  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1058  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1059  * array of cell ids. Pay attention that after conversion all algorithms work slower
1060  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1061  * conversion due presence of invalid ids in the array of cells to convert, as a
1062  * result \a this mesh contains some already converted elements. In this case the 2D
1063  * mesh remains valid but 3D mesh becomes \b inconsistent!
1064  *  \warning This method can significantly modify the order of geometric types in \a this,
1065  *          hence, to write this mesh to the MED file, its cells must be sorted using
1066  *          sortCellsInMEDFileFrmt().
1067  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1068  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1069  *         cellIdsToConvertBg.
1070  *  \throw If the coordinates array is not set.
1071  *  \throw If the nodal connectivity of cells is node defined.
1072  *  \throw If dimension of \a this mesh is not either 2 or 3.
1073  *
1074  *  \if ENABLE_EXAMPLES
1075  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1076  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1077  *  \endif
1078  */
1079 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1080 {
1081   checkFullyDefined();
1082   int dim=getMeshDimension();
1083   if(dim<2 || dim>3)
1084     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1085   int nbOfCells(getNumberOfCells());
1086   if(dim==2)
1087     {
1088       const int *connIndex=_nodal_connec_index->getConstPointer();
1089       int *conn=_nodal_connec->getPointer();
1090       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1091         {
1092           if(*iter>=0 && *iter<nbOfCells)
1093             {
1094               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1095               if(!cm.isQuadratic())
1096                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1097               else
1098                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1099             }
1100           else
1101             {
1102               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1103               oss << " in range [0," << nbOfCells << ") !";
1104               throw INTERP_KERNEL::Exception(oss.str().c_str());
1105             }
1106         }
1107     }
1108   else
1109     {
1110       int *connIndex(_nodal_connec_index->getPointer());
1111       const int *connOld(_nodal_connec->getConstPointer());
1112       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1113       std::vector<bool> toBeDone(nbOfCells,false);
1114       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1115         {
1116           if(*iter>=0 && *iter<nbOfCells)
1117             toBeDone[*iter]=true;
1118           else
1119             {
1120               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1121               oss << " in range [0," << nbOfCells << ") !";
1122               throw INTERP_KERNEL::Exception(oss.str().c_str());
1123             }
1124         }
1125       for(int cellId=0;cellId<nbOfCells;cellId++)
1126         {
1127           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1128           int lgthOld(posP1-pos-1);
1129           if(toBeDone[cellId])
1130             {
1131               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1132               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1133               int *tmp(new int[nbOfFaces*lgthOld+1]);
1134               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1135               for(unsigned j=0;j<nbOfFaces;j++)
1136                 {
1137                   INTERP_KERNEL::NormalizedCellType type;
1138                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1139                   work+=offset;
1140                   *work++=-1;
1141                 }
1142               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1143               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1144               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1145               delete [] tmp;
1146             }
1147           else
1148             {
1149               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1150               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1151             }
1152         }
1153       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1154     }
1155   computeTypes();
1156 }
1157
1158 /*!
1159  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1160  * polyhedrons (if \a this is a 3D mesh).
1161  *  \warning As this method is purely for user-friendliness and no optimization is
1162  *          done to avoid construction of a useless vector, this method can be costly
1163  *          in memory.
1164  *  \throw If the coordinates array is not set.
1165  *  \throw If the nodal connectivity of cells is node defined.
1166  *  \throw If dimension of \a this mesh is not either 2 or 3.
1167  */
1168 void MEDCouplingUMesh::convertAllToPoly()
1169 {
1170   int nbOfCells=getNumberOfCells();
1171   std::vector<int> cellIds(nbOfCells);
1172   for(int i=0;i<nbOfCells;i++)
1173     cellIds[i]=i;
1174   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1175 }
1176
1177 /*!
1178  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1179  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1180  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1181  * base facet of the volume and the second half of nodes describes an opposite facet
1182  * having the same number of nodes as the base one. This method converts such
1183  * connectivity to a valid polyhedral format where connectivity of each facet is
1184  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1185  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1186  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1187  * a correct orientation of the first facet of a polyhedron, else orientation of a
1188  * corrected cell is reverse.<br>
1189  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1190  * it releases the user from boring description of polyhedra connectivity in the valid
1191  * format.
1192  *  \throw If \a this->getMeshDimension() != 3.
1193  *  \throw If \a this->getSpaceDimension() != 3.
1194  *  \throw If the nodal connectivity of cells is not defined.
1195  *  \throw If the coordinates array is not set.
1196  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1197  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1198  *
1199  *  \if ENABLE_EXAMPLES
1200  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1201  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1202  *  \endif
1203  */
1204 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1205 {
1206   checkFullyDefined();
1207   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1208     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1209   int nbOfCells=getNumberOfCells();
1210   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1211   newCi->alloc(nbOfCells+1,1);
1212   int *newci=newCi->getPointer();
1213   const int *ci=_nodal_connec_index->getConstPointer();
1214   const int *c=_nodal_connec->getConstPointer();
1215   newci[0]=0;
1216   for(int i=0;i<nbOfCells;i++)
1217     {
1218       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1219       if(type==INTERP_KERNEL::NORM_POLYHED)
1220         {
1221           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1222             {
1223               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1224               throw INTERP_KERNEL::Exception(oss.str().c_str());
1225             }
1226           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1227           if(n2%2!=0)
1228             {
1229               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 !";
1230               throw INTERP_KERNEL::Exception(oss.str().c_str());
1231             }
1232           int n1=(int)(n2/2);
1233           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)
1234         }
1235       else
1236         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1237     }
1238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1239   newC->alloc(newci[nbOfCells],1);
1240   int *newc=newC->getPointer();
1241   for(int i=0;i<nbOfCells;i++)
1242     {
1243       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1244       if(type==INTERP_KERNEL::NORM_POLYHED)
1245         {
1246           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1247           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1248           *newc++=-1;
1249           for(std::size_t j=0;j<n1;j++)
1250             {
1251               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1252               newc[n1+5*j]=-1;
1253               newc[n1+5*j+1]=c[ci[i]+1+j];
1254               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1255               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1256               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1257             }
1258           newc+=n1*6;
1259         }
1260       else
1261         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1262     }
1263   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1264   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1265 }
1266
1267
1268 /*!
1269  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1270  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1271  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1272  *          to write this mesh to the MED file, its cells must be sorted using
1273  *          sortCellsInMEDFileFrmt().
1274  * \return \c true if at least one cell has been converted, \c false else. In the
1275  *         last case the nodal connectivity remains unchanged.
1276  * \throw If the coordinates array is not set.
1277  * \throw If the nodal connectivity of cells is not defined.
1278  * \throw If \a this->getMeshDimension() < 0.
1279  */
1280 bool MEDCouplingUMesh::unPolyze()
1281 {
1282   checkFullyDefined();
1283   int mdim=getMeshDimension();
1284   if(mdim<0)
1285     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1286   if(mdim<=1)
1287     return false;
1288   int nbOfCells=getNumberOfCells();
1289   if(nbOfCells<1)
1290     return false;
1291   int initMeshLgth=getMeshLength();
1292   int *conn=_nodal_connec->getPointer();
1293   int *index=_nodal_connec_index->getPointer();
1294   int posOfCurCell=0;
1295   int newPos=0;
1296   int lgthOfCurCell;
1297   bool ret=false;
1298   for(int i=0;i<nbOfCells;i++)
1299     {
1300       lgthOfCurCell=index[i+1]-posOfCurCell;
1301       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1302       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1303       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1304       int newLgth;
1305       if(cm.isDynamic())
1306         {
1307           switch(cm.getDimension())
1308           {
1309             case 2:
1310               {
1311                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1312                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1313                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1314                 break;
1315               }
1316             case 3:
1317               {
1318                 int nbOfFaces,lgthOfPolyhConn;
1319                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1320                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1321                 break;
1322               }
1323             case 1:
1324               {
1325                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1326                 break;
1327               }
1328           }
1329           ret=ret || (newType!=type);
1330           conn[newPos]=newType;
1331           newPos+=newLgth+1;
1332           posOfCurCell=index[i+1];
1333           index[i+1]=newPos;
1334         }
1335       else
1336         {
1337           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1338           newPos+=lgthOfCurCell;
1339           posOfCurCell+=lgthOfCurCell;
1340           index[i+1]=newPos;
1341         }
1342     }
1343   if(newPos!=initMeshLgth)
1344     _nodal_connec->reAlloc(newPos);
1345   if(ret)
1346     computeTypes();
1347   return ret;
1348 }
1349
1350 /*!
1351  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1352  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1353  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1354  *
1355  * \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 
1356  *             precision.
1357  */
1358 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1359 {
1360   checkFullyDefined();
1361   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1362     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1363   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1364   coords->recenterForMaxPrecision(eps);
1365   //
1366   int nbOfCells=getNumberOfCells();
1367   const int *conn=_nodal_connec->getConstPointer();
1368   const int *index=_nodal_connec_index->getConstPointer();
1369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1370   connINew->alloc(nbOfCells+1,1);
1371   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1373   bool changed=false;
1374   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1375     {
1376       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1377         {
1378           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1379           changed=true;
1380         }
1381       else
1382         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1383       *connINewPtr=connNew->getNumberOfTuples();
1384     }
1385   if(changed)
1386     setConnectivity(connNew,connINew,false);
1387 }
1388
1389 /*!
1390  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1391  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1392  * the format of returned DataArrayInt instance.
1393  * 
1394  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1395  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1396  */
1397 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1398 {
1399   checkConnectivityFullyDefined();
1400   int nbOfCells=getNumberOfCells();
1401   const int *connIndex=_nodal_connec_index->getConstPointer();
1402   const int *conn=_nodal_connec->getConstPointer();
1403   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1404   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1405   std::vector<bool> retS(maxElt,false);
1406   for(int i=0;i<nbOfCells;i++)
1407     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1408       if(conn[j]>=0)
1409         retS[conn[j]]=true;
1410   int sz=0;
1411   for(int i=0;i<maxElt;i++)
1412     if(retS[i])
1413       sz++;
1414   DataArrayInt *ret=DataArrayInt::New();
1415   ret->alloc(sz,1);
1416   int *retPtr=ret->getPointer();
1417   for(int i=0;i<maxElt;i++)
1418     if(retS[i])
1419       *retPtr++=i;
1420   return ret;
1421 }
1422
1423 /*!
1424  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1425  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1426  */
1427 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1428 {
1429   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1430   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1431   for(int i=0;i<nbOfCells;i++)
1432     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1433       if(conn[j]>=0)
1434         {
1435           if(conn[j]<nbOfNodes)
1436             nodeIdsInUse[conn[j]]=true;
1437           else
1438             {
1439               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1440               throw INTERP_KERNEL::Exception(oss.str().c_str());
1441             }
1442         }
1443 }
1444
1445 /*!
1446  * Finds nodes not used in any cell and returns an array giving a new id to every node
1447  * by excluding the unused nodes, for which the array holds -1. The result array is
1448  * a mapping in "Old to New" mode. 
1449  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1450  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1451  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1452  *          if the node is unused or a new id else. The caller is to delete this
1453  *          array using decrRef() as it is no more needed.  
1454  *  \throw If the coordinates array is not set.
1455  *  \throw If the nodal connectivity of cells is not defined.
1456  *  \throw If the nodal connectivity includes an invalid id.
1457  *
1458  *  \if ENABLE_EXAMPLES
1459  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1460  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1461  *  \endif
1462  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1463  */
1464 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1465 {
1466   nbrOfNodesInUse=-1;
1467   int nbOfNodes(getNumberOfNodes());
1468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1469   ret->alloc(nbOfNodes,1);
1470   int *traducer=ret->getPointer();
1471   std::fill(traducer,traducer+nbOfNodes,-1);
1472   int nbOfCells=getNumberOfCells();
1473   const int *connIndex=_nodal_connec_index->getConstPointer();
1474   const int *conn=_nodal_connec->getConstPointer();
1475   for(int i=0;i<nbOfCells;i++)
1476     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1477       if(conn[j]>=0)
1478         {
1479           if(conn[j]<nbOfNodes)
1480             traducer[conn[j]]=1;
1481           else
1482             {
1483               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1484               throw INTERP_KERNEL::Exception(oss.str().c_str());
1485             }
1486         }
1487   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1488   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1489   return ret.retn();
1490 }
1491
1492 /*!
1493  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1494  * For each cell in \b this the number of nodes constituting cell is computed.
1495  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1496  * So for pohyhedrons some nodes can be counted several times in the returned result.
1497  * 
1498  * \return a newly allocated array
1499  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1500  */
1501 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1502 {
1503   checkConnectivityFullyDefined();
1504   int nbOfCells=getNumberOfCells();
1505   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1506   ret->alloc(nbOfCells,1);
1507   int *retPtr=ret->getPointer();
1508   const int *conn=getNodalConnectivity()->getConstPointer();
1509   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1510   for(int i=0;i<nbOfCells;i++,retPtr++)
1511     {
1512       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1513         *retPtr=connI[i+1]-connI[i]-1;
1514       else
1515         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1516     }
1517   return ret.retn();
1518 }
1519
1520 /*!
1521  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1522  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1523  *
1524  * \return DataArrayInt * - new object to be deallocated by the caller.
1525  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1526  */
1527 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1528 {
1529   checkConnectivityFullyDefined();
1530   int nbOfCells=getNumberOfCells();
1531   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1532   ret->alloc(nbOfCells,1);
1533   int *retPtr=ret->getPointer();
1534   const int *conn=getNodalConnectivity()->getConstPointer();
1535   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1536   for(int i=0;i<nbOfCells;i++,retPtr++)
1537     {
1538       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1539       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1540         *retPtr=(int)s.size();
1541       else
1542         {
1543           s.erase(-1);
1544           *retPtr=(int)s.size();
1545         }
1546     }
1547   return ret.retn();
1548 }
1549
1550 /*!
1551  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1552  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1553  * 
1554  * \return a newly allocated array
1555  */
1556 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1557 {
1558   checkConnectivityFullyDefined();
1559   int nbOfCells=getNumberOfCells();
1560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1561   ret->alloc(nbOfCells,1);
1562   int *retPtr=ret->getPointer();
1563   const int *conn=getNodalConnectivity()->getConstPointer();
1564   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1565   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1566     {
1567       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1568       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1569     }
1570   return ret.retn();
1571 }
1572
1573 /*!
1574  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1575  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1576  * array mean that the corresponding old node is no more used. 
1577  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1578  *           this->getNumberOfNodes() before call of this method. The caller is to
1579  *           delete this array using decrRef() as it is no more needed. 
1580  *  \throw If the coordinates array is not set.
1581  *  \throw If the nodal connectivity of cells is not defined.
1582  *  \throw If the nodal connectivity includes an invalid id.
1583  *  \sa areAllNodesFetched
1584  *
1585  *  \if ENABLE_EXAMPLES
1586  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1587  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1588  *  \endif
1589  */
1590 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1591 {
1592   return MEDCouplingPointSet::zipCoordsTraducer();
1593 }
1594
1595 /*!
1596  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1597  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1598  */
1599 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1600 {
1601   switch(compType)
1602   {
1603     case 0:
1604       return AreCellsEqual0(conn,connI,cell1,cell2);
1605     case 1:
1606       return AreCellsEqual1(conn,connI,cell1,cell2);
1607     case 2:
1608       return AreCellsEqual2(conn,connI,cell1,cell2);
1609     case 3:
1610       return AreCellsEqual3(conn,connI,cell1,cell2);
1611     case 7:
1612       return AreCellsEqual7(conn,connI,cell1,cell2);
1613   }
1614   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1615 }
1616
1617 /*!
1618  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1619  */
1620 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1621 {
1622   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1623     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1624   return 0;
1625 }
1626
1627 /*!
1628  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1629  */
1630 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1631 {
1632   int sz=connI[cell1+1]-connI[cell1];
1633   if(sz==connI[cell2+1]-connI[cell2])
1634     {
1635       if(conn[connI[cell1]]==conn[connI[cell2]])
1636         {
1637           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1638           unsigned dim=cm.getDimension();
1639           if(dim!=3)
1640             {
1641               if(dim!=1)
1642                 {
1643                   int sz1=2*(sz-1);
1644                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1645                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1646                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1647                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1648                   return work!=tmp+sz1?1:0;
1649                 }
1650               else
1651                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1652             }
1653           else
1654             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1655         }
1656     }
1657   return 0;
1658 }
1659
1660 /*!
1661  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1662  */
1663 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1664 {
1665   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1666     {
1667       if(conn[connI[cell1]]==conn[connI[cell2]])
1668         {
1669           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1670           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1671           return s1==s2?1:0;
1672         }
1673     }
1674   return 0;
1675 }
1676
1677 /*!
1678  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1679  */
1680 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1681 {
1682   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1683     {
1684       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1685       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1686       return s1==s2?1:0;
1687     }
1688   return 0;
1689 }
1690
1691 /*!
1692  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1693  */
1694 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1695 {
1696   int sz=connI[cell1+1]-connI[cell1];
1697   if(sz==connI[cell2+1]-connI[cell2])
1698     {
1699       if(conn[connI[cell1]]==conn[connI[cell2]])
1700         {
1701           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1702           unsigned dim=cm.getDimension();
1703           if(dim!=3)
1704             {
1705               if(dim!=1)
1706                 {
1707                   int sz1=2*(sz-1);
1708                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1709                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1710                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1711                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1712                   if(work!=tmp+sz1)
1713                     return 1;
1714                   else
1715                     {
1716                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1717                       std::reverse_iterator<int *> it2((int *)tmp);
1718                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1719                         return 2;
1720                       else
1721                         return 0;
1722                     }
1723
1724                   return work!=tmp+sz1?1:0;
1725                 }
1726               else
1727                 {//case of SEG2 and SEG3
1728                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1729                     return 1;
1730                   if(!cm.isQuadratic())
1731                     {
1732                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1733                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1734                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1735                         return 2;
1736                       return 0;
1737                     }
1738                   else
1739                     {
1740                       if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
1741                         return 2;
1742                       return 0;
1743                     }
1744                 }
1745             }
1746           else
1747             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1748         }
1749     }
1750   return 0;
1751 }
1752
1753 /*!
1754  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1755  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1756  * and result remains unchanged.
1757  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1758  * If in 'candidates' pool -1 value is considered as an empty value.
1759  * WARNING this method returns only ONE set of result !
1760  */
1761 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1762 {
1763   if(candidates.size()<1)
1764     return false;
1765   bool ret=false;
1766   std::vector<int>::const_iterator iter=candidates.begin();
1767   int start=(*iter++);
1768   for(;iter!=candidates.end();iter++)
1769     {
1770       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1771       if(status!=0)
1772         {
1773           if(!ret)
1774             {
1775               result->pushBackSilent(start);
1776               ret=true;
1777             }
1778           if(status==1)
1779             result->pushBackSilent(*iter);
1780           else
1781             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1782         }
1783     }
1784   return ret;
1785 }
1786
1787 /*!
1788  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1789  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1790  *
1791  * \param [in] compType input specifying the technique used to compare cells each other.
1792  *   - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1793  *   - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1794  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1795  *   - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1796  * can be used for users not sensitive to orientation of cell
1797  * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1798  * \param [out] commonCells
1799  * \param [out] commonCellsI
1800  * \return the correspondance array old to new in a newly allocated array.
1801  * 
1802  */
1803 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1804 {
1805   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1806   getReverseNodalConnectivity(revNodal,revNodalI);
1807   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1808 }
1809
1810 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1811                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1812 {
1813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1814   int nbOfCells=nodalI->getNumberOfTuples()-1;
1815   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1816   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1817   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1818   std::vector<bool> isFetched(nbOfCells,false);
1819   if(startCellId==0)
1820     {
1821       for(int i=0;i<nbOfCells;i++)
1822         {
1823           if(!isFetched[i])
1824             {
1825               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1826               std::vector<int> v,v2;
1827               if(connOfNode!=connPtr+connIPtr[i+1])
1828                 {
1829                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1830                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1831                   connOfNode++;
1832                 }
1833               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1834                 if(*connOfNode>=0)
1835                   {
1836                     v=v2;
1837                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1838                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1839                     v2.resize(std::distance(v2.begin(),it));
1840                   }
1841               if(v2.size()>1)
1842                 {
1843                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1844                     {
1845                       int pos=commonCellsI->back();
1846                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1847                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1848                         isFetched[*it]=true;
1849                     }
1850                 }
1851             }
1852         }
1853     }
1854   else
1855     {
1856       for(int i=startCellId;i<nbOfCells;i++)
1857         {
1858           if(!isFetched[i])
1859             {
1860               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1861               std::vector<int> v,v2;
1862               if(connOfNode!=connPtr+connIPtr[i+1])
1863                 {
1864                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1865                   connOfNode++;
1866                 }
1867               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1868                 if(*connOfNode>=0)
1869                   {
1870                     v=v2;
1871                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1872                     v2.resize(std::distance(v2.begin(),it));
1873                   }
1874               if(v2.size()>1)
1875                 {
1876                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1877                     {
1878                       int pos=commonCellsI->back();
1879                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1880                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1881                         isFetched[*it]=true;
1882                     }
1883                 }
1884             }
1885         }
1886     }
1887   commonCellsArr=commonCells.retn();
1888   commonCellsIArr=commonCellsI.retn();
1889 }
1890
1891 /*!
1892  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1893  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1894  * than \a other->getNumberOfCells() in the returned array means that there is no
1895  * corresponding cell in \a this mesh.
1896  * It is expected that \a this and \a other meshes share the same node coordinates
1897  * array, if it is not so an exception is thrown. 
1898  *  \param [in] other - the mesh to compare with.
1899  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1900  *         valid values [0,1,2], see zipConnectivityTraducer().
1901  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1902  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1903  *         values. The caller is to delete this array using
1904  *         decrRef() as it is no more needed.
1905  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1906  *         mesh.
1907  *
1908  *  \if ENABLE_EXAMPLES
1909  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1910  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1911  *  \endif
1912  *  \sa checkDeepEquivalOnSameNodesWith()
1913  *  \sa checkGeoEquivalWith()
1914  */
1915 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1916 {
1917   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1918   int nbOfCells=getNumberOfCells();
1919   static const int possibleCompType[]={0,1,2};
1920   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1921     {
1922       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1923       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1924       oss << " !";
1925       throw INTERP_KERNEL::Exception(oss.str().c_str());
1926     }
1927   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1928   arr=o2n->substr(nbOfCells);
1929   arr->setName(other->getName());
1930   int tmp;
1931   if(other->getNumberOfCells()==0)
1932     return true;
1933   return arr->getMaxValue(tmp)<nbOfCells;
1934 }
1935
1936 /*!
1937  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1938  * This method tries to determine if \b other is fully included in \b this.
1939  * The main difference is that this method is not expected to throw exception.
1940  * This method has two outputs :
1941  *
1942  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1943  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1944  */
1945 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1946 {
1947   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1948   DataArrayInt *commonCells=0,*commonCellsI=0;
1949   int thisNbCells=getNumberOfCells();
1950   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1952   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1953   int otherNbCells=other->getNumberOfCells();
1954   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1955   arr2->alloc(otherNbCells,1);
1956   arr2->fillWithZero();
1957   int *arr2Ptr=arr2->getPointer();
1958   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1959   for(int i=0;i<nbOfCommon;i++)
1960     {
1961       int start=commonCellsPtr[commonCellsIPtr[i]];
1962       if(start<thisNbCells)
1963         {
1964           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1965             {
1966               int sig=commonCellsPtr[j]>0?1:-1;
1967               int val=std::abs(commonCellsPtr[j])-1;
1968               if(val>=thisNbCells)
1969                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1970             }
1971         }
1972     }
1973   arr2->setName(other->getName());
1974   if(arr2->presenceOfValue(0))
1975     return false;
1976   arr=arr2.retn();
1977   return true;
1978 }
1979
1980 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1981 {
1982   if(!other)
1983     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1984   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1985   if(!otherC)
1986     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1987   std::vector<const MEDCouplingUMesh *> ms(2);
1988   ms[0]=this;
1989   ms[1]=otherC;
1990   return MergeUMeshesOnSameCoords(ms);
1991 }
1992
1993 /*!
1994  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1995  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1996  * cellIds is not given explicitely but by a range python like.
1997  * 
1998  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1999  * \return a newly allocated
2000  * 
2001  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2002  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2003  */
2004 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2005 {
2006   if(getMeshDimension()!=-1)
2007     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2008   else
2009     {
2010       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2011       if(newNbOfCells!=1)
2012         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2013       if(start!=0)
2014         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2015       incrRef();
2016       return const_cast<MEDCouplingUMesh *>(this);
2017     }
2018 }
2019
2020 /*!
2021  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2022  * The result mesh shares or not the node coordinates array with \a this mesh depending
2023  * on \a keepCoords parameter.
2024  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2025  *           to write this mesh to the MED file, its cells must be sorted using
2026  *           sortCellsInMEDFileFrmt().
2027  *  \param [in] begin - an array of cell ids to include to the new mesh.
2028  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2029  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2030  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2031  *         by calling zipCoords().
2032  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2033  *         to delete this mesh using decrRef() as it is no more needed. 
2034  *  \throw If the coordinates array is not set.
2035  *  \throw If the nodal connectivity of cells is not defined.
2036  *  \throw If any cell id in the array \a begin is not valid.
2037  *
2038  *  \if ENABLE_EXAMPLES
2039  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2040  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2041  *  \endif
2042  */
2043 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2044 {
2045   if(getMeshDimension()!=-1)
2046     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2047   else
2048     {
2049       if(end-begin!=1)
2050         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2051       if(begin[0]!=0)
2052         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2053       incrRef();
2054       return const_cast<MEDCouplingUMesh *>(this);
2055     }
2056 }
2057
2058 /*!
2059  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2060  *
2061  * This method allows to partially modify some cells in \b this (whose list is specified by [ \b cellIdsBg, \b cellIdsEnd ) ) with cells coming in \b otherOnSameCoordsThanThis.
2062  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2063  * The number of cells of \b this will remain the same with this method.
2064  *
2065  * \param [in] begin begin of cell ids (included) of cells in this to assign
2066  * \param [in] end end of cell ids (excluded) of cells in this to assign
2067  * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd ).
2068  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2069  */
2070 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2071 {
2072   checkConnectivityFullyDefined();
2073   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2074   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2075     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2076   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2077     {
2078       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2079       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2080       throw INTERP_KERNEL::Exception(oss.str().c_str());
2081     }
2082   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2083   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2084     {
2085       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2086       throw INTERP_KERNEL::Exception(oss.str().c_str());
2087     }
2088   int nbOfCells=getNumberOfCells();
2089   bool easyAssign=true;
2090   const int *connI=_nodal_connec_index->getConstPointer();
2091   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2092   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2093     {
2094       if(*it>=0 && *it<nbOfCells)
2095         {
2096           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2097         }
2098       else
2099         {
2100           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2101           throw INTERP_KERNEL::Exception(oss.str().c_str());
2102         }
2103     }
2104   if(easyAssign)
2105     {
2106       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2107       computeTypes();
2108     }
2109   else
2110     {
2111       DataArrayInt *arrOut=0,*arrIOut=0;
2112       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2113                                                arrOut,arrIOut);
2114       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2115       setConnectivity(arrOut,arrIOut,true);
2116     }
2117 }
2118
2119 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2120 {
2121   checkConnectivityFullyDefined();
2122   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2123   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2124     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2125   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2126     {
2127       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2128       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2129       throw INTERP_KERNEL::Exception(oss.str().c_str());
2130     }
2131   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2132   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2133     {
2134       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2135       throw INTERP_KERNEL::Exception(oss.str().c_str());
2136     }
2137   int nbOfCells=getNumberOfCells();
2138   bool easyAssign=true;
2139   const int *connI=_nodal_connec_index->getConstPointer();
2140   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2141   int it=start;
2142   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2143     {
2144       if(it>=0 && it<nbOfCells)
2145         {
2146           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2147         }
2148       else
2149         {
2150           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2151           throw INTERP_KERNEL::Exception(oss.str().c_str());
2152         }
2153     }
2154   if(easyAssign)
2155     {
2156       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2157       computeTypes();
2158     }
2159   else
2160     {
2161       DataArrayInt *arrOut=0,*arrIOut=0;
2162       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2163                                                 arrOut,arrIOut);
2164       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2165       setConnectivity(arrOut,arrIOut,true);
2166     }
2167 }                      
2168
2169 /*!
2170  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2171  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2172  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2173  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2174  *
2175  * \param [in] begin input start of array of node ids.
2176  * \param [in] end input end of array of node ids.
2177  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2178  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2179  */
2180 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2181 {
2182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2183   checkConnectivityFullyDefined();
2184   int tmp=-1;
2185   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2186   std::vector<bool> fastFinder(sz,false);
2187   for(const int *work=begin;work!=end;work++)
2188     if(*work>=0 && *work<sz)
2189       fastFinder[*work]=true;
2190   int nbOfCells=getNumberOfCells();
2191   const int *conn=getNodalConnectivity()->getConstPointer();
2192   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2193   for(int i=0;i<nbOfCells;i++)
2194     {
2195       int ref=0,nbOfHit=0;
2196       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2197         if(*work2>=0)
2198           {
2199             ref++;
2200             if(fastFinder[*work2])
2201               nbOfHit++;
2202           }
2203       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2204         cellIdsKept->pushBackSilent(i);
2205     }
2206   cellIdsKeptArr=cellIdsKept.retn();
2207 }
2208
2209 /*!
2210  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2211  * this->getMeshDimension(), that bound some cells of \a this mesh.
2212  * The cells of lower dimension to include to the result mesh are selected basing on
2213  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2214  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2215  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2216  * created mesh shares the node coordinates array with \a this mesh. 
2217  *  \param [in] begin - the array of node ids.
2218  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2219  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2220  *         array \a begin are added, else cells whose any node is in the
2221  *         array \a begin are added.
2222  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2223  *         to delete this mesh using decrRef() as it is no more needed. 
2224  *  \throw If the coordinates array is not set.
2225  *  \throw If the nodal connectivity of cells is not defined.
2226  *  \throw If any node id in \a begin is not valid.
2227  *
2228  *  \if ENABLE_EXAMPLES
2229  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2230  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2231  *  \endif
2232  */
2233 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2234 {
2235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2236   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2237   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2238   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2239   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2240 }
2241
2242 /*!
2243  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2244  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2245  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2246  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2247  *         by calling zipCoords().
2248  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2249  *         to delete this mesh using decrRef() as it is no more needed. 
2250  *  \throw If the coordinates array is not set.
2251  *  \throw If the nodal connectivity of cells is not defined.
2252  *
2253  *  \if ENABLE_EXAMPLES
2254  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2255  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2256  *  \endif
2257  */
2258 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2259 {
2260   DataArrayInt *desc=DataArrayInt::New();
2261   DataArrayInt *descIndx=DataArrayInt::New();
2262   DataArrayInt *revDesc=DataArrayInt::New();
2263   DataArrayInt *revDescIndx=DataArrayInt::New();
2264   //
2265   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2266   revDesc->decrRef();
2267   desc->decrRef();
2268   descIndx->decrRef();
2269   int nbOfCells=meshDM1->getNumberOfCells();
2270   const int *revDescIndxC=revDescIndx->getConstPointer();
2271   std::vector<int> boundaryCells;
2272   for(int i=0;i<nbOfCells;i++)
2273     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2274       boundaryCells.push_back(i);
2275   revDescIndx->decrRef();
2276   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2277   return ret;
2278 }
2279
2280 /*!
2281  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2282  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2283  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2284  */
2285 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2286 {
2287   checkFullyDefined();
2288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2292   //
2293   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2294   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2295   //
2296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2298   const int *revDescPtr=revDesc->getConstPointer();
2299   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2300   int nbOfCells=getNumberOfCells();
2301   std::vector<bool> ret1(nbOfCells,false);
2302   int sz=0;
2303   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2304     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2305       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2306   //
2307   DataArrayInt *ret2=DataArrayInt::New();
2308   ret2->alloc(sz,1);
2309   int *ret2Ptr=ret2->getPointer();
2310   sz=0;
2311   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2312     if(*it)
2313       *ret2Ptr++=sz;
2314   ret2->setName("BoundaryCells");
2315   return ret2;
2316 }
2317
2318 /*!
2319  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2320  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2321  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2322  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2323  *
2324  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2325  * This method method returns cells ids set s = s1 + s2 where :
2326  * 
2327  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2328  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2329  *
2330  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2331  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2332  *
2333  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2334  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2335  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2336  */
2337 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2338 {
2339   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2340     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2341   checkConnectivityFullyDefined();
2342   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2343   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2344     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2349   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2350   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2351   DataArrayInt *idsOtherInConsti=0;
2352   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2353   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2354   if(!b)
2355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2356   std::set<int> s1;
2357   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2358     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2361   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2362   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2363   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2364   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2365   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2366   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2367   neighThisPartAuto=0;
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2369   const int li[2]={0,1};
2370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2371   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2373   s_renum1->sort();
2374   //
2375   cellIdsRk0=s0arr.retn();
2376   cellIdsRk1=s_renum1.retn();
2377 }
2378
2379 /*!
2380  * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is
2381  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2382  * 
2383  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2384  */
2385 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2386 {
2387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2391   //
2392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2393   revDesc=0; desc=0; descIndx=0;
2394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2395   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2396   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2397 }
2398
2399 /*!
2400  * Finds nodes lying on the boundary of \a this mesh.
2401  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2402  *          nodes. The caller is to delete this array using decrRef() as it is no
2403  *          more needed.
2404  *  \throw If the coordinates array is not set.
2405  *  \throw If the nodal connectivity of cells is node defined.
2406  *
2407  *  \if ENABLE_EXAMPLES
2408  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2409  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2410  *  \endif
2411  */
2412 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2413 {
2414   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2415   return skin->computeFetchedNodeIds();
2416 }
2417
2418 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2419 {
2420   incrRef();
2421   return const_cast<MEDCouplingUMesh *>(this);
2422 }
2423
2424 /*!
2425  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2426  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2427  * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords.
2428  * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2429  * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate.
2430  *
2431  * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
2432  *             parameter is altered during the call.
2433  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2434  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2435  * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2436  *
2437  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2438  */
2439 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2440                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2441 {
2442   checkFullyDefined();
2443   otherDimM1OnSameCoords.checkFullyDefined();
2444   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2446   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2447     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2448   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2449   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2451   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2452   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2453   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2455   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2457   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2458   //
2459   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2461   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2462   DataArrayInt *idsTmp=0;
2463   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2465   if(!b)
2466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2467   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2468   DataArrayInt *tmp0=0,*tmp1=0;
2469   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2473   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2474   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2475   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2476   //
2477   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2478   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2479   nodeIdsToDuplicate=s3.retn();
2480 }
2481
2482 /*!
2483  * This method operates a modification of the connectivity and coords in \b this.
2484  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2485  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2486  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2487  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2488  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2489  * 
2490  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2491  * 
2492  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2493  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2494  */
2495 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2496 {
2497   int nbOfNodes=getNumberOfNodes();
2498   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2499   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2500 }
2501
2502 /*!
2503  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2504  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2505  *
2506  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2507  *
2508  * \sa renumberNodesInConn
2509  */
2510 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2511 {
2512   checkConnectivityFullyDefined();
2513   int *conn(getNodalConnectivity()->getPointer());
2514   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2515   int nbOfCells(getNumberOfCells());
2516   for(int i=0;i<nbOfCells;i++)
2517     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2518       {
2519         int& node=conn[iconn];
2520         if(node>=0)//avoid polyhedron separator
2521           {
2522             node+=offset;
2523           }
2524       }
2525   _nodal_connec->declareAsNew();
2526   updateTime();
2527 }
2528
2529 /*!
2530  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2531  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2532  *  of a big mesh.
2533  */
2534 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2535 {
2536   checkConnectivityFullyDefined();
2537   int *conn(getNodalConnectivity()->getPointer());
2538   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2539   int nbOfCells(getNumberOfCells());
2540   for(int i=0;i<nbOfCells;i++)
2541     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2542       {
2543         int& node=conn[iconn];
2544         if(node>=0)//avoid polyhedron separator
2545           {
2546             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2547             if(it!=newNodeNumbersO2N.end())
2548               {
2549                 node=(*it).second;
2550               }
2551             else
2552               {
2553                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2554                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2555               }
2556           }
2557       }
2558   _nodal_connec->declareAsNew();
2559   updateTime();
2560 }
2561
2562 /*!
2563  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2564  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2565  * This method is a generalization of shiftNodeNumbersInConn().
2566  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2567  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2568  *         this->getNumberOfNodes(), in "Old to New" mode. 
2569  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2570  *  \throw If the nodal connectivity of cells is not defined.
2571  *
2572  *  \if ENABLE_EXAMPLES
2573  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2574  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2575  *  \endif
2576  */
2577 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2578 {
2579   checkConnectivityFullyDefined();
2580   int *conn=getNodalConnectivity()->getPointer();
2581   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2582   int nbOfCells(getNumberOfCells());
2583   for(int i=0;i<nbOfCells;i++)
2584     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2585       {
2586         int& node=conn[iconn];
2587         if(node>=0)//avoid polyhedron separator
2588           {
2589             node=newNodeNumbersO2N[node];
2590           }
2591       }
2592   _nodal_connec->declareAsNew();
2593   updateTime();
2594 }
2595
2596 /*!
2597  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2598  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2599  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2600  * 
2601  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2602  */
2603 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2604 {
2605   checkConnectivityFullyDefined();
2606   int *conn=getNodalConnectivity()->getPointer();
2607   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2608   int nbOfCells=getNumberOfCells();
2609   for(int i=0;i<nbOfCells;i++)
2610     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2611       {
2612         int& node=conn[iconn];
2613         if(node>=0)//avoid polyhedron separator
2614           {
2615             node+=delta;
2616           }
2617       }
2618   _nodal_connec->declareAsNew();
2619   updateTime();
2620 }
2621
2622 /*!
2623  * This method operates a modification of the connectivity in \b this.
2624  * 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.
2625  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2626  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2627  * 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
2628  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2629  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2630  * 
2631  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2632  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2633  * 
2634  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2635  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2636  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2637  */
2638 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2639 {
2640   checkConnectivityFullyDefined();
2641   std::map<int,int> m;
2642   int val=offset;
2643   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2644     m[*work]=val;
2645   int *conn=getNodalConnectivity()->getPointer();
2646   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2647   int nbOfCells=getNumberOfCells();
2648   for(int i=0;i<nbOfCells;i++)
2649     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2650       {
2651         int& node=conn[iconn];
2652         if(node>=0)//avoid polyhedron separator
2653           {
2654             std::map<int,int>::iterator it=m.find(node);
2655             if(it!=m.end())
2656               node=(*it).second;
2657           }
2658       }
2659   updateTime();
2660 }
2661
2662 /*!
2663  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2664  *
2665  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2666  * After the call of this method the number of cells remains the same as before.
2667  *
2668  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2669  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2670  * be strictly in [0;this->getNumberOfCells()).
2671  *
2672  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2673  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2674  * should be contained in[0;this->getNumberOfCells()).
2675  * 
2676  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2677  */
2678 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2679 {
2680   checkConnectivityFullyDefined();
2681   int nbCells=getNumberOfCells();
2682   const int *array=old2NewBg;
2683   if(check)
2684     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2685   //
2686   const int *conn=_nodal_connec->getConstPointer();
2687   const int *connI=_nodal_connec_index->getConstPointer();
2688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2690   const int *n2oPtr=n2o->begin();
2691   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2692   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2693   newConn->copyStringInfoFrom(*_nodal_connec);
2694   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2695   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2696   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2697   //
2698   int *newC=newConn->getPointer();
2699   int *newCI=newConnI->getPointer();
2700   int loc=0;
2701   newCI[0]=loc;
2702   for(int i=0;i<nbCells;i++)
2703     {
2704       int pos=n2oPtr[i];
2705       int nbOfElts=connI[pos+1]-connI[pos];
2706       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2707       loc+=nbOfElts;
2708       newCI[i+1]=loc;
2709     }
2710   //
2711   setConnectivity(newConn,newConnI);
2712   if(check)
2713     free(const_cast<int *>(array));
2714 }
2715
2716 /*!
2717  * Finds cells whose bounding boxes intersect a given bounding box.
2718  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2719  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2720  *         zMax (if in 3D). 
2721  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2722  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2723  *         extent of the bounding box of cell to produce an addition to this bounding box.
2724  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2725  *         cells. The caller is to delete this array using decrRef() as it is no more
2726  *         needed. 
2727  *  \throw If the coordinates array is not set.
2728  *  \throw If the nodal connectivity of cells is not defined.
2729  *
2730  *  \if ENABLE_EXAMPLES
2731  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2732  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2733  *  \endif
2734  */
2735 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2736 {
2737   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2738   if(getMeshDimension()==-1)
2739     {
2740       elems->pushBackSilent(0);
2741       return elems.retn();
2742     }
2743   int dim=getSpaceDimension();
2744   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2745   const int* conn      = getNodalConnectivity()->getConstPointer();
2746   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2747   const double* coords = getCoords()->getConstPointer();
2748   int nbOfCells=getNumberOfCells();
2749   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2750     {
2751       for (int i=0; i<dim; i++)
2752         {
2753           elem_bb[i*2]=std::numeric_limits<double>::max();
2754           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2755         }
2756
2757       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2758         {
2759           int node= conn[inode];
2760           if(node>=0)//avoid polyhedron separator
2761             {
2762               for (int idim=0; idim<dim; idim++)
2763                 {
2764                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2765                     {
2766                       elem_bb[idim*2] = coords[node*dim+idim] ;
2767                     }
2768                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2769                     {
2770                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2771                     }
2772                 }
2773             }
2774         }
2775       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2776         elems->pushBackSilent(ielem);
2777     }
2778   return elems.retn();
2779 }
2780
2781 /*!
2782  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2783  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2784  * added in 'elems' parameter.
2785  */
2786 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2787 {
2788   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2789   if(getMeshDimension()==-1)
2790     {
2791       elems->pushBackSilent(0);
2792       return elems.retn();
2793     }
2794   int dim=getSpaceDimension();
2795   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2796   const int* conn      = getNodalConnectivity()->getConstPointer();
2797   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2798   const double* coords = getCoords()->getConstPointer();
2799   int nbOfCells=getNumberOfCells();
2800   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2801     {
2802       for (int i=0; i<dim; i++)
2803         {
2804           elem_bb[i*2]=std::numeric_limits<double>::max();
2805           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2806         }
2807
2808       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2809         {
2810           int node= conn[inode];
2811           if(node>=0)//avoid polyhedron separator
2812             {
2813               for (int idim=0; idim<dim; idim++)
2814                 {
2815                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2816                     {
2817                       elem_bb[idim*2] = coords[node*dim+idim] ;
2818                     }
2819                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2820                     {
2821                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2822                     }
2823                 }
2824             }
2825         }
2826       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2827         elems->pushBackSilent(ielem);
2828     }
2829   return elems.retn();
2830 }
2831
2832 /*!
2833  * Returns a type of a cell by its id.
2834  *  \param [in] cellId - the id of the cell of interest.
2835  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2836  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2837  */
2838 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2839 {
2840   const int *ptI=_nodal_connec_index->getConstPointer();
2841   const int *pt=_nodal_connec->getConstPointer();
2842   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2843     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2844   else
2845     {
2846       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2847       throw INTERP_KERNEL::Exception(oss.str().c_str());
2848     }
2849 }
2850
2851 /*!
2852  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2853  * This method does not throw exception if geometric type \a type is not in \a this.
2854  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2855  * The coordinates array is not considered here.
2856  *
2857  * \param [in] type the geometric type
2858  * \return cell ids in this having geometric type \a type.
2859  */
2860 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2861 {
2862
2863   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2864   ret->alloc(0,1);
2865   checkConnectivityFullyDefined();
2866   int nbCells=getNumberOfCells();
2867   int mdim=getMeshDimension();
2868   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2869   if(mdim!=(int)cm.getDimension())
2870     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2871   const int *ptI=_nodal_connec_index->getConstPointer();
2872   const int *pt=_nodal_connec->getConstPointer();
2873   for(int i=0;i<nbCells;i++)
2874     {
2875       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2876         ret->pushBackSilent(i);
2877     }
2878   return ret.retn();
2879 }
2880
2881 /*!
2882  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2883  */
2884 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2885 {
2886   const int *ptI=_nodal_connec_index->getConstPointer();
2887   const int *pt=_nodal_connec->getConstPointer();
2888   int nbOfCells=getNumberOfCells();
2889   int ret=0;
2890   for(int i=0;i<nbOfCells;i++)
2891     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2892       ret++;
2893   return ret;
2894 }
2895
2896 /*!
2897  * Returns the nodal connectivity of a given cell.
2898  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2899  * all returned node ids can be used in getCoordinatesOfNode().
2900  *  \param [in] cellId - an id of the cell of interest.
2901  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2902  *         cleared before the appending.
2903  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2904  */
2905 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2906 {
2907   const int *ptI=_nodal_connec_index->getConstPointer();
2908   const int *pt=_nodal_connec->getConstPointer();
2909   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2910     if(*w>=0)
2911       conn.push_back(*w);
2912 }
2913
2914 std::string MEDCouplingUMesh::simpleRepr() const
2915 {
2916   static const char msg0[]="No coordinates specified !";
2917   std::ostringstream ret;
2918   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2919   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2920   int tmpp1,tmpp2;
2921   double tt=getTime(tmpp1,tmpp2);
2922   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2923   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2924   if(_mesh_dim>=-1)
2925     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2926   else
2927     { ret << " Mesh dimension has not been set or is invalid !"; }
2928   if(_coords!=0)
2929     {
2930       const int spaceDim=getSpaceDimension();
2931       ret << spaceDim << "\nInfo attached on space dimension : ";
2932       for(int i=0;i<spaceDim;i++)
2933         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2934       ret << "\n";
2935     }
2936   else
2937     ret << msg0 << "\n";
2938   ret << "Number of nodes : ";
2939   if(_coords!=0)
2940     ret << getNumberOfNodes() << "\n";
2941   else
2942     ret << msg0 << "\n";
2943   ret << "Number of cells : ";
2944   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2945     ret << getNumberOfCells() << "\n";
2946   else
2947     ret << "No connectivity specified !" << "\n";
2948   ret << "Cell types present : ";
2949   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2950     {
2951       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2952       ret << cm.getRepr() << " ";
2953     }
2954   ret << "\n";
2955   return ret.str();
2956 }
2957
2958 std::string MEDCouplingUMesh::advancedRepr() const
2959 {
2960   std::ostringstream ret;
2961   ret << simpleRepr();
2962   ret << "\nCoordinates array : \n___________________\n\n";
2963   if(_coords)
2964     _coords->reprWithoutNameStream(ret);
2965   else
2966     ret << "No array set !\n";
2967   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2968   reprConnectivityOfThisLL(ret);
2969   return ret.str();
2970 }
2971
2972 /*!
2973  * This method returns a C++ code that is a dump of \a this.
2974  * This method will throw if this is not fully defined.
2975  */
2976 std::string MEDCouplingUMesh::cppRepr() const
2977 {
2978   static const char coordsName[]="coords";
2979   static const char connName[]="conn";
2980   static const char connIName[]="connI";
2981   checkFullyDefined();
2982   std::ostringstream ret; ret << "// coordinates" << std::endl;
2983   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2984   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2985   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2986   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2987   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2988   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2989   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2990   return ret.str();
2991 }
2992
2993 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2994 {
2995   std::ostringstream ret;
2996   reprConnectivityOfThisLL(ret);
2997   return ret.str();
2998 }
2999
3000 /*!
3001  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3002  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3003  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3004  * some algos).
3005  * 
3006  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3007  * 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
3008  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3009  */
3010 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3011 {
3012   int mdim=getMeshDimension();
3013   if(mdim<0)
3014     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3015   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3017   bool needToCpyCT=true;
3018   if(!_nodal_connec)
3019     {
3020       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3021       needToCpyCT=false;
3022     }
3023   else
3024     {
3025       tmp1=_nodal_connec;
3026       tmp1->incrRef();
3027     }
3028   if(!_nodal_connec_index)
3029     {
3030       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3031       needToCpyCT=false;
3032     }
3033   else
3034     {
3035       tmp2=_nodal_connec_index;
3036       tmp2->incrRef();
3037     }
3038   ret->setConnectivity(tmp1,tmp2,false);
3039   if(needToCpyCT)
3040     ret->_types=_types;
3041   if(!_coords)
3042     {
3043       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3044       ret->setCoords(coords);
3045     }
3046   else
3047     ret->setCoords(_coords);
3048   return ret.retn();
3049 }
3050
3051 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3052 {
3053   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3054     {
3055       int nbOfCells=getNumberOfCells();
3056       const int *c=_nodal_connec->getConstPointer();
3057       const int *ci=_nodal_connec_index->getConstPointer();
3058       for(int i=0;i<nbOfCells;i++)
3059         {
3060           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3061           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3062           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3063           stream << "\n";
3064         }
3065     }
3066   else
3067     stream << "Connectivity not defined !\n";
3068 }
3069
3070 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3071 {
3072   const int *ptI=_nodal_connec_index->getConstPointer();
3073   const int *pt=_nodal_connec->getConstPointer();
3074   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3075     return ptI[cellId+1]-ptI[cellId]-1;
3076   else
3077     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3078 }
3079
3080 /*!
3081  * Returns types of cells of the specified part of \a this mesh.
3082  * This method avoids computing sub-mesh explicitely to get its types.
3083  *  \param [in] begin - an array of cell ids of interest.
3084  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3085  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3086  *         describing the cell types. 
3087  *  \throw If the coordinates array is not set.
3088  *  \throw If the nodal connectivity of cells is not defined.
3089  *  \sa getAllGeoTypes()
3090  */
3091 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3092 {
3093   checkFullyDefined();
3094   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3095   const int *conn=_nodal_connec->getConstPointer();
3096   const int *connIndex=_nodal_connec_index->getConstPointer();
3097   for(const int *w=begin;w!=end;w++)
3098     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3099   return ret;
3100 }
3101
3102 /*!
3103  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3104  * a set of types of cells constituting \a this mesh. 
3105  * This method is for advanced users having prepared their connectivity before. For
3106  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3107  *  \param [in] conn - the nodal connectivity array. 
3108  *  \param [in] connIndex - the nodal connectivity index array.
3109  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3110  *         mesh is updated.
3111  */
3112 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3113 {
3114   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3115   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3116   if(isComputingTypes)
3117     computeTypes();
3118   declareAsNew();
3119 }
3120
3121 /*!
3122  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3123  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3124  */
3125 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3126     _nodal_connec(0),_nodal_connec_index(0),
3127     _types(other._types)
3128 {
3129   if(other._nodal_connec)
3130     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3131   if(other._nodal_connec_index)
3132     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3133 }
3134
3135 MEDCouplingUMesh::~MEDCouplingUMesh()
3136 {
3137   if(_nodal_connec)
3138     _nodal_connec->decrRef();
3139   if(_nodal_connec_index)
3140     _nodal_connec_index->decrRef();
3141 }
3142
3143 /*!
3144  * Recomputes a set of cell types of \a this mesh. For more info see
3145  * \ref MEDCouplingUMeshNodalConnectivity.
3146  */
3147 void MEDCouplingUMesh::computeTypes()
3148 {
3149   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3150 }
3151
3152 /*!
3153  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3154  */
3155 void MEDCouplingUMesh::checkFullyDefined() const
3156 {
3157   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3158     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3159 }
3160
3161 /*!
3162  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3163  */
3164 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3165 {
3166   if(!_nodal_connec_index || !_nodal_connec)
3167     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3168 }
3169
3170 /*!
3171  * Returns a number of cells constituting \a this mesh. 
3172  *  \return int - the number of cells in \a this mesh.
3173  *  \throw If the nodal connectivity of cells is not defined.
3174  */
3175 int MEDCouplingUMesh::getNumberOfCells() const
3176
3177   if(_nodal_connec_index)
3178     return _nodal_connec_index->getNumberOfTuples()-1;
3179   else
3180     if(_mesh_dim==-1)
3181       return 1;
3182     else
3183       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3184 }
3185
3186 /*!
3187  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3188  * mesh. For more info see \ref MEDCouplingMeshesPage.
3189  *  \return int - the dimension of \a this mesh.
3190  *  \throw If the mesh dimension is not defined using setMeshDimension().
3191  */
3192 int MEDCouplingUMesh::getMeshDimension() const
3193 {
3194   if(_mesh_dim<-1)
3195     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3196   return _mesh_dim;
3197 }
3198
3199 /*!
3200  * Returns a length of the nodal connectivity array.
3201  * This method is for test reason. Normally the integer returned is not useable by
3202  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3203  *  \return int - the length of the nodal connectivity array.
3204  */
3205 int MEDCouplingUMesh::getMeshLength() const
3206 {
3207   return _nodal_connec->getNbOfElems();
3208 }
3209
3210 /*!
3211  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3212  */
3213 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3214 {
3215   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3216   tinyInfo.push_back(getMeshDimension());
3217   tinyInfo.push_back(getNumberOfCells());
3218   if(_nodal_connec)
3219     tinyInfo.push_back(getMeshLength());
3220   else
3221     tinyInfo.push_back(-1);
3222 }
3223
3224 /*!
3225  * First step of unserialization process.
3226  */
3227 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3228 {
3229   return tinyInfo[6]<=0;
3230 }
3231
3232 /*!
3233  * Second step of serialization process.
3234  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3235  */
3236 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3237 {
3238   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3239   if(tinyInfo[5]!=-1)
3240     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3241 }
3242
3243 /*!
3244  * Third and final step of serialization process.
3245  */
3246 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3247 {
3248   MEDCouplingPointSet::serialize(a1,a2);
3249   if(getMeshDimension()>-1)
3250     {
3251       a1=DataArrayInt::New();
3252       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3253       int *ptA1=a1->getPointer();
3254       const int *conn=getNodalConnectivity()->getConstPointer();
3255       const int *index=getNodalConnectivityIndex()->getConstPointer();
3256       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3257       std::copy(conn,conn+getMeshLength(),ptA1);
3258     }
3259   else
3260     a1=0;
3261 }
3262
3263 /*!
3264  * Second and final unserialization process.
3265  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3266  */
3267 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3268 {
3269   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3270   setMeshDimension(tinyInfo[5]);
3271   if(tinyInfo[7]!=-1)
3272     {
3273       // Connectivity
3274       const int *recvBuffer=a1->getConstPointer();
3275       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3276       myConnecIndex->alloc(tinyInfo[6]+1,1);
3277       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3278       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3279       myConnec->alloc(tinyInfo[7],1);
3280       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3281       setConnectivity(myConnec, myConnecIndex);
3282     }
3283 }
3284
3285 /*!
3286  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3287  * CellIds are given using range specified by a start an end and step.
3288  */
3289 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3290 {
3291   checkFullyDefined();
3292   int ncell=getNumberOfCells();
3293   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3294   ret->_mesh_dim=_mesh_dim;
3295   ret->setCoords(_coords);
3296   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3298   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3299   int work=start;
3300   const int *conn=_nodal_connec->getConstPointer();
3301   const int *connIndex=_nodal_connec_index->getConstPointer();
3302   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3303     {
3304       if(work>=0 && work<ncell)
3305         {
3306           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3307         }
3308       else
3309         {
3310           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3311           throw INTERP_KERNEL::Exception(oss.str().c_str());
3312         }
3313     }
3314   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3315   int *newConnPtr=newConn->getPointer();
3316   std::set<INTERP_KERNEL::NormalizedCellType> types;
3317   work=start;
3318   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3319     {
3320       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3321       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3322     }
3323   ret->setConnectivity(newConn,newConnI,false);
3324   ret->_types=types;
3325   ret->copyTinyInfoFrom(this);
3326   return ret.retn();
3327 }
3328
3329 /*!
3330  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3331  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3332  * The return newly allocated mesh will share the same coordinates as \a this.
3333  */
3334 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3335 {
3336   checkConnectivityFullyDefined();
3337   int ncell=getNumberOfCells();
3338   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3339   ret->_mesh_dim=_mesh_dim;
3340   ret->setCoords(_coords);
3341   std::size_t nbOfElemsRet=std::distance(begin,end);
3342   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3343   connIndexRet[0]=0;
3344   const int *conn=_nodal_connec->getConstPointer();
3345   const int *connIndex=_nodal_connec_index->getConstPointer();
3346   int newNbring=0;
3347   for(const int *work=begin;work!=end;work++,newNbring++)
3348     {
3349       if(*work>=0 && *work<ncell)
3350         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3351       else
3352         {
3353           free(connIndexRet);
3354           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3355           throw INTERP_KERNEL::Exception(oss.str().c_str());
3356         }
3357     }
3358   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3359   int *connRetWork=connRet;
3360   std::set<INTERP_KERNEL::NormalizedCellType> types;
3361   for(const int *work=begin;work!=end;work++)
3362     {
3363       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3364       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3365     }
3366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3367   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3369   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3370   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3371   ret->_types=types;
3372   ret->copyTinyInfoFrom(this);
3373   return ret.retn();
3374 }
3375
3376 /*!
3377  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3378  * mesh.<br>
3379  * For 1D cells, the returned field contains lengths.<br>
3380  * For 2D cells, the returned field contains areas.<br>
3381  * For 3D cells, the returned field contains volumes.
3382  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3383  *         orientation, i.e. the volume is always positive.
3384  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3385  *         and one time . The caller is to delete this field using decrRef() as it is no
3386  *         more needed.
3387  */
3388 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3389 {
3390   std::string name="MeasureOfMesh_";
3391   name+=getName();
3392   int nbelem=getNumberOfCells();
3393   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3394   field->setName(name);
3395   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3396   array->alloc(nbelem,1);
3397   double *area_vol=array->getPointer();
3398   field->setArray(array) ; array=0;
3399   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3400   field->synchronizeTimeWithMesh();
3401   if(getMeshDimension()!=-1)
3402     {
3403       int ipt;
3404       INTERP_KERNEL::NormalizedCellType type;
3405       int dim_space=getSpaceDimension();
3406       const double *coords=getCoords()->getConstPointer();
3407       const int *connec=getNodalConnectivity()->getConstPointer();
3408       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3409       for(int iel=0;iel<nbelem;iel++)
3410         {
3411           ipt=connec_index[iel];
3412           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3413           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);
3414         }
3415       if(isAbs)
3416         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3417     }
3418   else
3419     {
3420       area_vol[0]=std::numeric_limits<double>::max();
3421     }
3422   return field.retn();
3423 }
3424
3425 /*!
3426  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3427  * mesh.<br>
3428  * For 1D cells, the returned array contains lengths.<br>
3429  * For 2D cells, the returned array contains areas.<br>
3430  * For 3D cells, the returned array contains volumes.
3431  * This method avoids building explicitly a part of \a this mesh to perform the work.
3432  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3433  *         orientation, i.e. the volume is always positive.
3434  *  \param [in] begin - an array of cell ids of interest.
3435  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3436  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3437  *          delete this array using decrRef() as it is no more needed.
3438  * 
3439  *  \if ENABLE_EXAMPLES
3440  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3441  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3442  *  \endif
3443  *  \sa getMeasureField()
3444  */
3445 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3446 {
3447   std::string name="PartMeasureOfMesh_";
3448   name+=getName();
3449   int nbelem=(int)std::distance(begin,end);
3450   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3451   array->setName(name);
3452   array->alloc(nbelem,1);
3453   double *area_vol=array->getPointer();
3454   if(getMeshDimension()!=-1)
3455     {
3456       int ipt;
3457       INTERP_KERNEL::NormalizedCellType type;
3458       int dim_space=getSpaceDimension();
3459       const double *coords=getCoords()->getConstPointer();
3460       const int *connec=getNodalConnectivity()->getConstPointer();
3461       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3462       for(const int *iel=begin;iel!=end;iel++)
3463         {
3464           ipt=connec_index[*iel];
3465           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3466           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3467         }
3468       if(isAbs)
3469         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3470     }
3471   else
3472     {
3473       area_vol[0]=std::numeric_limits<double>::max();
3474     }
3475   return array.retn();
3476 }
3477
3478 /*!
3479  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3480  * \a this one. The returned field contains the dual cell volume for each corresponding
3481  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3482  *  the dual mesh in P1 sens of \a this.<br>
3483  * For 1D cells, the returned field contains lengths.<br>
3484  * For 2D cells, the returned field contains areas.<br>
3485  * For 3D cells, the returned field contains volumes.
3486  * This method is useful to check "P1*" conservative interpolators.
3487  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3488  *         orientation, i.e. the volume is always positive.
3489  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3490  *          nodes and one time. The caller is to delete this array using decrRef() as
3491  *          it is no more needed.
3492  */
3493 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3494 {
3495   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3496   std::string name="MeasureOnNodeOfMesh_";
3497   name+=getName();
3498   int nbNodes=getNumberOfNodes();
3499   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3500   double cst=1./((double)getMeshDimension()+1.);
3501   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3502   array->alloc(nbNodes,1);
3503   double *valsToFill=array->getPointer();
3504   std::fill(valsToFill,valsToFill+nbNodes,0.);
3505   const double *values=tmp->getArray()->getConstPointer();
3506   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3507   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3508   getReverseNodalConnectivity(da,daInd);
3509   const int *daPtr=da->getConstPointer();
3510   const int *daIPtr=daInd->getConstPointer();
3511   for(int i=0;i<nbNodes;i++)
3512     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3513       valsToFill[i]+=cst*values[*cell];
3514   ret->setMesh(this);
3515   ret->setArray(array);
3516   return ret.retn();
3517 }
3518
3519 /*!
3520  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3521  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3522  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3523  * and are normalized.
3524  * <br> \a this can be either 
3525  * - a  2D mesh in 2D or 3D space or 
3526  * - an 1D mesh in 2D space.
3527  * 
3528  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3529  *          cells and one time. The caller is to delete this field using decrRef() as
3530  *          it is no more needed.
3531  *  \throw If the nodal connectivity of cells is not defined.
3532  *  \throw If the coordinates array is not set.
3533  *  \throw If the mesh dimension is not set.
3534  *  \throw If the mesh and space dimension is not as specified above.
3535  */
3536 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3537 {
3538   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3539     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3540   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3541   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3542   int nbOfCells=getNumberOfCells();
3543   int nbComp=getMeshDimension()+1;
3544   array->alloc(nbOfCells,nbComp);
3545   double *vals=array->getPointer();
3546   const int *connI=_nodal_connec_index->getConstPointer();
3547   const int *conn=_nodal_connec->getConstPointer();
3548   const double *coords=_coords->getConstPointer();
3549   if(getMeshDimension()==2)
3550     {
3551       if(getSpaceDimension()==3)
3552         {
3553           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3554           const double *locPtr=loc->getConstPointer();
3555           for(int i=0;i<nbOfCells;i++,vals+=3)
3556             {
3557               int offset=connI[i];
3558               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3559               double n=INTERP_KERNEL::norm<3>(vals);
3560               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3561             }
3562         }
3563       else
3564         {
3565           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3566           const double *isAbsPtr=isAbs->getArray()->begin();
3567           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3568             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3569         }
3570     }
3571   else//meshdimension==1
3572     {
3573       double tmp[2];
3574       for(int i=0;i<nbOfCells;i++)
3575         {
3576           int offset=connI[i];
3577           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3578           double n=INTERP_KERNEL::norm<2>(tmp);
3579           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3580           *vals++=-tmp[1];
3581           *vals++=tmp[0];
3582         }
3583     }
3584   ret->setArray(array);
3585   ret->setMesh(this);
3586   ret->synchronizeTimeWithSupport();
3587   return ret.retn();
3588 }
3589
3590 /*!
3591  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3592  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3593  * and are normalized.
3594  * <br> \a this can be either 
3595  * - a  2D mesh in 2D or 3D space or 
3596  * - an 1D mesh in 2D space.
3597  * 
3598  * This method avoids building explicitly a part of \a this mesh to perform the work.
3599  *  \param [in] begin - an array of cell ids of interest.
3600  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3601  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3602  *          cells and one time. The caller is to delete this field using decrRef() as
3603  *          it is no more needed.
3604  *  \throw If the nodal connectivity of cells is not defined.
3605  *  \throw If the coordinates array is not set.
3606  *  \throw If the mesh dimension is not set.
3607  *  \throw If the mesh and space dimension is not as specified above.
3608  *  \sa buildOrthogonalField()
3609  *
3610  *  \if ENABLE_EXAMPLES
3611  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3612  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3613  *  \endif
3614  */
3615 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3616 {
3617   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3618     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3619   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3620   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3621   std::size_t nbelems=std::distance(begin,end);
3622   int nbComp=getMeshDimension()+1;
3623   array->alloc((int)nbelems,nbComp);
3624   double *vals=array->getPointer();
3625   const int *connI=_nodal_connec_index->getConstPointer();
3626   const int *conn=_nodal_connec->getConstPointer();
3627   const double *coords=_coords->getConstPointer();
3628   if(getMeshDimension()==2)
3629     {
3630       if(getSpaceDimension()==3)
3631         {
3632           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3633           const double *locPtr=loc->getConstPointer();
3634           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3635             {
3636               int offset=connI[*i];
3637               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3638               double n=INTERP_KERNEL::norm<3>(vals);
3639               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3640             }
3641         }
3642       else
3643         {
3644           for(std::size_t i=0;i<nbelems;i++)
3645             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3646         }
3647     }
3648   else//meshdimension==1
3649     {
3650       double tmp[2];
3651       for(const int *i=begin;i!=end;i++)
3652         {
3653           int offset=connI[*i];
3654           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3655           double n=INTERP_KERNEL::norm<2>(tmp);
3656           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3657           *vals++=-tmp[1];
3658           *vals++=tmp[0];
3659         }
3660     }
3661   ret->setArray(array);
3662   ret->setMesh(this);
3663   ret->synchronizeTimeWithSupport();
3664   return ret.retn();
3665 }
3666
3667 /*!
3668  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3669  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3670  * and are \b not normalized.
3671  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3672  *          cells and one time. The caller is to delete this field using decrRef() as
3673  *          it is no more needed.
3674  *  \throw If the nodal connectivity of cells is not defined.
3675  *  \throw If the coordinates array is not set.
3676  *  \throw If \a this->getMeshDimension() != 1.
3677  *  \throw If \a this mesh includes cells of type other than SEG2.
3678  */
3679 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3680 {
3681   if(getMeshDimension()!=1)
3682     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3683   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3684     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3685   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3686   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3687   int nbOfCells=getNumberOfCells();
3688   int spaceDim=getSpaceDimension();
3689   array->alloc(nbOfCells,spaceDim);
3690   double *pt=array->getPointer();
3691   const double *coo=getCoords()->getConstPointer();
3692   std::vector<int> conn;
3693   conn.reserve(2);
3694   for(int i=0;i<nbOfCells;i++)
3695     {
3696       conn.resize(0);
3697       getNodeIdsOfCell(i,conn);
3698       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3699     }
3700   ret->setArray(array);
3701   ret->setMesh(this);
3702   ret->synchronizeTimeWithSupport();
3703   return ret.retn();
3704 }
3705
3706 /*!
3707  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3708  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3709  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3710  * from. If a result face is shared by two 3D cells, then the face in included twice in
3711  * the result mesh.
3712  *  \param [in] origin - 3 components of a point defining location of the plane.
3713  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3714  *         must be greater than 1e-6.
3715  *  \param [in] eps - half-thickness of the plane.
3716  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3717  *         producing correspondent 2D cells. The caller is to delete this array
3718  *         using decrRef() as it is no more needed.
3719  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3720  *         not share the node coordinates array with \a this mesh. The caller is to
3721  *         delete this mesh using decrRef() as it is no more needed.  
3722  *  \throw If the coordinates array is not set.
3723  *  \throw If the nodal connectivity of cells is not defined.
3724  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3725  *  \throw If magnitude of \a vec is less than 1e-6.
3726  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3727  *  \throw If \a this includes quadratic cells.
3728  */
3729 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3730 {
3731   checkFullyDefined();
3732   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3733     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3734   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3735   if(candidates->empty())
3736     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3737   std::vector<int> nodes;
3738   DataArrayInt *cellIds1D=0;
3739   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3740   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3741   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3742   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3743   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3744   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3745   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3746   revDesc2=0; revDescIndx2=0;
3747   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3748   revDesc1=0; revDescIndx1=0;
3749   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3751   //
3752   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3753   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3754     cut3DCurve[*it]=-1;
3755   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3756   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3757   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3758                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3759                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3761   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3762   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3763   if(cellIds2->empty())
3764     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3765   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3766   ret->setCoords(mDesc1->getCoords());
3767   ret->setConnectivity(conn,connI,true);
3768   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3769   return ret.retn();
3770 }
3771
3772 /*!
3773  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3774 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
3775 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3776 the result mesh.
3777  *  \param [in] origin - 3 components of a point defining location of the plane.
3778  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3779  *         must be greater than 1e-6.
3780  *  \param [in] eps - half-thickness of the plane.
3781  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3782  *         producing correspondent segments. The caller is to delete this array
3783  *         using decrRef() as it is no more needed.
3784  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3785  *         mesh in 3D space. This mesh does not share the node coordinates array with
3786  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3787  *         no more needed. 
3788  *  \throw If the coordinates array is not set.
3789  *  \throw If the nodal connectivity of cells is not defined.
3790  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3791  *  \throw If magnitude of \a vec is less than 1e-6.
3792  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3793  *  \throw If \a this includes quadratic cells.
3794  */
3795 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3796 {
3797   checkFullyDefined();
3798   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3799     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3800   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3801   if(candidates->empty())
3802     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3803   std::vector<int> nodes;
3804   DataArrayInt *cellIds1D=0;
3805   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3806   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3811   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3812   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3814   //
3815   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3816   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3817     cut3DCurve[*it]=-1;
3818   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3819   int ncellsSub=subMesh->getNumberOfCells();
3820   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3821   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3822                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3823                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3824   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3825   conn->alloc(0,1);
3826   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3827   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3828   for(int i=0;i<ncellsSub;i++)
3829     {
3830       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3831         {
3832           if(cut3DSurf[i].first!=-2)
3833             {
3834               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3835               connI->pushBackSilent(conn->getNumberOfTuples());
3836               cellIds2->pushBackSilent(i);
3837             }
3838           else
3839             {
3840               int cellId3DSurf=cut3DSurf[i].second;
3841               int offset=nodalI[cellId3DSurf]+1;
3842               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3843               for(int j=0;j<nbOfEdges;j++)
3844                 {
3845                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3846                   connI->pushBackSilent(conn->getNumberOfTuples());
3847                   cellIds2->pushBackSilent(cellId3DSurf);
3848                 }
3849             }
3850         }
3851     }
3852   if(cellIds2->empty())
3853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3854   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3855   ret->setCoords(mDesc1->getCoords());
3856   ret->setConnectivity(conn,connI,true);
3857   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3858   return ret.retn();
3859 }
3860
3861 /*!
3862  * Finds cells whose bounding boxes intersect a given plane.
3863  *  \param [in] origin - 3 components of a point defining location of the plane.
3864  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3865  *         must be greater than 1e-6.
3866  *  \param [in] eps - half-thickness of the plane.
3867  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3868  *         cells. The caller is to delete this array using decrRef() as it is no more
3869  *         needed.
3870  *  \throw If the coordinates array is not set.
3871  *  \throw If the nodal connectivity of cells is not defined.
3872  *  \throw If \a this->getSpaceDimension() != 3.
3873  *  \throw If magnitude of \a vec is less than 1e-6.
3874  *  \sa buildSlice3D()
3875  */
3876 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3877 {
3878   checkFullyDefined();
3879   if(getSpaceDimension()!=3)
3880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3881   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3882   if(normm<1e-6)
3883     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3884   double vec2[3];
3885   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3886   double angle=acos(vec[2]/normm);
3887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3888   double bbox[6];
3889   if(angle>eps)
3890     {
3891       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3892       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3893       if(normm2/normm>1e-6)
3894         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3895       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3896       mw->setCoords(coo);
3897       mw->getBoundingBox(bbox);
3898       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3899       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3900     }
3901   else
3902     {
3903       getBoundingBox(bbox);
3904       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3905       cellIds=getCellsInBoundingBox(bbox,eps);
3906     }
3907   return cellIds.retn();
3908 }
3909
3910 /*!
3911  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3912  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3913  * No consideration of coordinate is done by this method.
3914  * 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)
3915  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3916  */
3917 bool MEDCouplingUMesh::isContiguous1D() const
3918 {
3919   if(getMeshDimension()!=1)
3920     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3921   int nbCells=getNumberOfCells();
3922   if(nbCells<1)
3923     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3924   const int *connI=_nodal_connec_index->getConstPointer();
3925   const int *conn=_nodal_connec->getConstPointer();
3926   int ref=conn[connI[0]+2];
3927   for(int i=1;i<nbCells;i++)
3928     {
3929       if(conn[connI[i]+1]!=ref)
3930         return false;
3931       ref=conn[connI[i]+2];
3932     }
3933   return true;
3934 }
3935
3936 /*!
3937  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3938  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3939  * \param pt reference point of the line
3940  * \param v normalized director vector of the line
3941  * \param eps max precision before throwing an exception
3942  * \param res output of size this->getNumberOfCells
3943  */
3944 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3945 {
3946   if(getMeshDimension()!=1)
3947     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3948   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3949     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3950   if(getSpaceDimension()!=3)
3951     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3952   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3953   const double *fPtr=f->getArray()->getConstPointer();
3954   double tmp[3];
3955   for(int i=0;i<getNumberOfCells();i++)
3956     {
3957       const double *tmp1=fPtr+3*i;
3958       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3959       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3960       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3961       double n1=INTERP_KERNEL::norm<3>(tmp);
3962       n1/=INTERP_KERNEL::norm<3>(tmp1);
3963       if(n1>eps)
3964         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3965     }
3966   const double *coo=getCoords()->getConstPointer();
3967   for(int i=0;i<getNumberOfNodes();i++)
3968     {
3969       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3970       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3971       res[i]=std::accumulate(tmp,tmp+3,0.);
3972     }
3973 }
3974
3975 /*!
3976  * 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. 
3977  * \a this is expected to be a mesh so that its space dimension is equal to its
3978  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3979  * 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).
3980  *
3981  * 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
3982  * 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).
3983  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3984  *
3985  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3986  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3987  *
3988  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3989  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3990  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3991  * \return the positive value of the distance.
3992  * \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
3993  * dimension - 1.
3994  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3995  */
3996 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3997 {
3998   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3999   if(meshDim!=spaceDim-1)
4000     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4001   if(meshDim!=2 && meshDim!=1)
4002     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4003   checkFullyDefined();
4004   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4005     { 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()); }
4006   DataArrayInt *ret1=0;
4007   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4008   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4009   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4010   cellId=*ret1Safe->begin();
4011   return *ret0->begin();
4012 }
4013
4014 /*!
4015  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4016  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4017  * 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
4018  * 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).
4019  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4020  * 
4021  * \a this is expected to be a mesh so that its space dimension is equal to its
4022  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4023  * 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).
4024  *
4025  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4026  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4027  *
4028  * \param [in] pts the list of points in which each tuple represents a point
4029  * \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.
4030  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4031  * \throw if number of components of \a pts is not equal to the space dimension.
4032  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4033  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4034  */
4035 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4036 {
4037   if(!pts)
4038     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4039   pts->checkAllocated();
4040   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4041   if(meshDim!=spaceDim-1)
4042     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4043   if(meshDim!=2 && meshDim!=1)
4044     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4045   if(pts->getNumberOfComponents()!=spaceDim)
4046     {
4047       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4048       throw INTERP_KERNEL::Exception(oss.str().c_str());
4049     }
4050   checkFullyDefined();
4051   int nbCells=getNumberOfCells();
4052   if(nbCells==0)
4053     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4054   int nbOfPts=pts->getNumberOfTuples();
4055   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4056   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4057   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4058   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4059   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4060   const double *bbox(bboxArr->begin());
4061   switch(spaceDim)
4062   {
4063     case 3:
4064       {
4065         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4066         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4067           {
4068             double x=std::numeric_limits<double>::max();
4069             std::vector<int> elems;
4070             myTree.getMinDistanceOfMax(ptsPtr,x);
4071             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4072             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4073           }
4074         break;
4075       }
4076     case 2:
4077       {
4078         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4079         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4080           {
4081             double x=std::numeric_limits<double>::max();
4082             std::vector<int> elems;
4083             myTree.getMinDistanceOfMax(ptsPtr,x);
4084             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4085             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4086           }
4087         break;
4088       }
4089     default:
4090       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4091   }
4092   cellIds=ret1.retn();
4093   return ret0.retn();
4094 }
4095
4096 /*!
4097  * \param [in] pt the start pointer (included) of the coordinates of the point
4098  * \param [in] cellIdsBg the start pointer (included) of cellIds
4099  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4100  * \param [in] nc nodal connectivity
4101  * \param [in] ncI nodal connectivity index
4102  * \param [in,out] ret0 the min distance between \a this and the external input point
4103  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4104  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4105  */
4106 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)
4107 {
4108   cellId=-1;
4109   ret0=std::numeric_limits<double>::max();
4110   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4111     {
4112       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4113       {
4114         case INTERP_KERNEL::NORM_TRI3:
4115           {
4116             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4117             if(tmp<ret0)
4118               { ret0=tmp; cellId=*zeCell; }
4119             break;
4120           }
4121         case INTERP_KERNEL::NORM_QUAD4:
4122         case INTERP_KERNEL::NORM_POLYGON:
4123           {
4124             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4125             if(tmp<ret0)
4126               { ret0=tmp; cellId=*zeCell; }
4127             break;
4128           }
4129         default:
4130           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4131       }
4132     }
4133 }
4134
4135 /*!
4136  * \param [in] pt the start pointer (included) of the coordinates of the point
4137  * \param [in] cellIdsBg the start pointer (included) of cellIds
4138  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4139  * \param [in] nc nodal connectivity
4140  * \param [in] ncI nodal connectivity index
4141  * \param [in,out] ret0 the min distance between \a this and the external input point
4142  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4143  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4144  */
4145 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)
4146 {
4147   cellId=-1;
4148   ret0=std::numeric_limits<double>::max();
4149   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4150     {
4151       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4152       {
4153         case INTERP_KERNEL::NORM_SEG2:
4154           {
4155             std::size_t uselessEntry=0;
4156             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4157             tmp=sqrt(tmp);
4158             if(tmp<ret0)
4159               { ret0=tmp; cellId=*zeCell; }
4160             break;
4161           }
4162         default:
4163           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4164       }
4165     }
4166 }
4167
4168 /*!
4169  * Finds cells in contact with a ball (i.e. a point with precision). 
4170  * 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.
4171  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4172  *
4173  * \warning This method is suitable if the caller intends to evaluate only one
4174  *          point, for more points getCellsContainingPoints() is recommended as it is
4175  *          faster. 
4176  *  \param [in] pos - array of coordinates of the ball central point.
4177  *  \param [in] eps - ball radius.
4178  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4179  *         if there are no such cells.
4180  *  \throw If the coordinates array is not set.
4181  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4182  */
4183 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4184 {
4185   std::vector<int> elts;
4186   getCellsContainingPoint(pos,eps,elts);
4187   if(elts.empty())
4188     return -1;
4189   return elts.front();
4190 }
4191
4192 /*!
4193  * Finds cells in contact with a ball (i.e. a point with precision).
4194  * 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.
4195  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4196  * \warning This method is suitable if the caller intends to evaluate only one
4197  *          point, for more points getCellsContainingPoints() is recommended as it is
4198  *          faster. 
4199  *  \param [in] pos - array of coordinates of the ball central point.
4200  *  \param [in] eps - ball radius.
4201  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4202  *         before inserting ids.
4203  *  \throw If the coordinates array is not set.
4204  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4205  *
4206  *  \if ENABLE_EXAMPLES
4207  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4208  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4209  *  \endif
4210  */
4211 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4212 {
4213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4214   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4215   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4216 }
4217
4218 /// @cond INTERNAL
4219
4220 namespace ParaMEDMEM
4221 {
4222   template<const int SPACEDIMM>
4223   class DummyClsMCUG
4224   {
4225   public:
4226     static const int MY_SPACEDIM=SPACEDIMM;
4227     static const int MY_MESHDIM=8;
4228     typedef int MyConnType;
4229     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4230     // begin
4231     // useless, but for windows compilation ...
4232     const double* getCoordinatesPtr() const { return 0; }
4233     const int* getConnectivityPtr() const { return 0; }
4234     const int* getConnectivityIndexPtr() const { return 0; }
4235     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4236     // end
4237   };
4238
4239   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4240   {
4241     INTERP_KERNEL::Edge *ret(0);
4242     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]));
4243     m[n0]=bg[0]; m[n1]=bg[1];
4244     switch(typ)
4245     {
4246       case INTERP_KERNEL::NORM_SEG2:
4247         {
4248           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4249           break;
4250         }
4251       case INTERP_KERNEL::NORM_SEG3:
4252         {
4253           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4254           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4255           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4256           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4257           bool colinearity(inters.areColinears());
4258           delete e1; delete e2;
4259           if(colinearity)
4260             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4261           else
4262             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4263           break;
4264         }
4265       default:
4266         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4267     }
4268     return ret;
4269   }
4270
4271   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4272   {
4273     INTERP_KERNEL::Edge *ret=0;
4274     switch(typ)
4275     {
4276       case INTERP_KERNEL::NORM_SEG2:
4277         {
4278           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4279           break;
4280         }
4281       case INTERP_KERNEL::NORM_SEG3:
4282         {
4283           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4284           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4285           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4286           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4287           bool colinearity=inters.areColinears();
4288           delete e1; delete e2;
4289           if(colinearity)
4290             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4291           else
4292             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4293           mapp2[bg[2]].second=false;
4294           break;
4295         }
4296       default:
4297         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4298     }
4299     return ret;
4300   }
4301
4302   /*!
4303    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4304    * the global mesh 'mDesc'.
4305    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4306    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4307    */
4308   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4309                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4310   {
4311     mapp.clear();
4312     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.
4313     const double *coo=mDesc->getCoords()->getConstPointer();
4314     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4315     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4316     std::set<int> s;
4317     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4318       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4319     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4320       {
4321         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4322         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4323       }
4324     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4325     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4326       {
4327         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4328         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4329       }
4330     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4331       {
4332         if((*it2).second.second)
4333           mapp[(*it2).second.first]=(*it2).first;
4334         ((*it2).second.first)->decrRef();
4335       }
4336     return ret;
4337   }
4338
4339   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4340   {
4341     if(nodeId>=offset2)
4342       {
4343         int locId=nodeId-offset2;
4344         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4345       }
4346     if(nodeId>=offset1)
4347       {
4348         int locId=nodeId-offset1;
4349         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4350       }
4351     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4352   }
4353
4354   /**
4355    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4356    */
4357   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4358                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4359                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4360   {
4361     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4362       {
4363         int eltId1=abs(*desc1)-1;
4364         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4365           {
4366             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4367             if(it==mappRev.end())
4368               {
4369                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4370                 mapp[node]=*it1;
4371                 mappRev[*it1]=node;
4372               }
4373           }
4374       }
4375   }
4376 }
4377
4378 /// @endcond
4379
4380 template<int SPACEDIM>
4381 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4382                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4383 {
4384   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4385   int *eltsIndexPtr(eltsIndex->getPointer());
4386   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4387   const double *bbox(bboxArr->begin());
4388   int nbOfCells=getNumberOfCells();
4389   const int *conn=_nodal_connec->getConstPointer();
4390   const int *connI=_nodal_connec_index->getConstPointer();
4391   double bb[2*SPACEDIM];
4392   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4393   for(int i=0;i<nbOfPoints;i++)
4394     {
4395       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4396       for(int j=0;j<SPACEDIM;j++)
4397         {
4398           bb[2*j]=pos[SPACEDIM*i+j];
4399           bb[2*j+1]=pos[SPACEDIM*i+j];
4400         }
4401       std::vector<int> candidates;
4402       myTree.getIntersectingElems(bb,candidates);
4403       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4404         {
4405           int sz(connI[(*iter)+1]-connI[*iter]-1);
4406           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4407           bool status(false);
4408           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4409             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4410           else
4411             {
4412               if(SPACEDIM!=2)
4413                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4414               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4415               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4416               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4417               INTERP_KERNEL::QuadraticPolygon *pol(0);
4418               for(int j=0;j<sz;j++)
4419                 {
4420                   int nodeId(conn[connI[*iter]+1+j]);
4421                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4422                 }
4423               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4424                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4425               else
4426                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4427               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4428               double a(0.),b(0.),c(0.);
4429               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4430               status=pol->isInOrOut2(n);
4431               delete pol; n->decrRef();
4432             }
4433           if(status)
4434             {
4435               eltsIndexPtr[i+1]++;
4436               elts->pushBackSilent(*iter);
4437             }
4438         }
4439     }
4440 }
4441 /*!
4442  * Finds cells in contact with several balls (i.e. points with precision).
4443  * This method is an extension of getCellContainingPoint() and
4444  * getCellsContainingPoint() for the case of multiple points.
4445  * 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.
4446  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4447  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4448  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4449  *         this->getSpaceDimension() * \a nbOfPoints 
4450  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4451  *  \param [in] eps - radius of balls (i.e. the precision).
4452  *  \param [out] elts - vector returning ids of found cells.
4453  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4454  *         dividing cell ids in \a elts into groups each referring to one
4455  *         point. Its every element (except the last one) is an index pointing to the
4456  *         first id of a group of cells. For example cells in contact with the *i*-th
4457  *         point are described by following range of indices:
4458  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4459  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4460  *         Number of cells in contact with the *i*-th point is
4461  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4462  *  \throw If the coordinates array is not set.
4463  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4464  *
4465  *  \if ENABLE_EXAMPLES
4466  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4467  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4468  *  \endif
4469  */
4470 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4471                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4472 {
4473   int spaceDim=getSpaceDimension();
4474   int mDim=getMeshDimension();
4475   if(spaceDim==3)
4476     {
4477       if(mDim==3)
4478         {
4479           const double *coords=_coords->getConstPointer();
4480           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4481         }
4482       /*else if(mDim==2)
4483         {
4484
4485         }*/
4486       else
4487         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4488     }
4489   else if(spaceDim==2)
4490     {
4491       if(mDim==2)
4492         {
4493           const double *coords=_coords->getConstPointer();
4494           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4495         }
4496       else
4497         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4498     }
4499   else if(spaceDim==1)
4500     {
4501       if(mDim==1)
4502         {
4503           const double *coords=_coords->getConstPointer();
4504           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4505         }
4506       else
4507         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4508     }
4509   else
4510     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4511 }
4512
4513 /*!
4514  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4515  * least two its edges intersect each other anywhere except their extremities. An
4516  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4517  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4518  *         cleared before filling in.
4519  *  \param [in] eps - precision.
4520  *  \throw If \a this->getMeshDimension() != 2.
4521  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4522  */
4523 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4524 {
4525   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4526   if(getMeshDimension()!=2)
4527     throw INTERP_KERNEL::Exception(msg);
4528   int spaceDim=getSpaceDimension();
4529   if(spaceDim!=2 && spaceDim!=3)
4530     throw INTERP_KERNEL::Exception(msg);
4531   const int *conn=_nodal_connec->getConstPointer();
4532   const int *connI=_nodal_connec_index->getConstPointer();
4533   int nbOfCells=getNumberOfCells();
4534   std::vector<double> cell2DinS2;
4535   for(int i=0;i<nbOfCells;i++)
4536     {
4537       int offset=connI[i];
4538       int nbOfNodesForCell=connI[i+1]-offset-1;
4539       if(nbOfNodesForCell<=3)
4540         continue;
4541       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4542       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4543       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4544         cells.push_back(i);
4545       cell2DinS2.clear();
4546     }
4547 }
4548
4549 /*!
4550  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4551  *
4552  * 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.
4553  * 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.
4554  * 
4555  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4556  * This convex envelop is computed using Jarvis march algorithm.
4557  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4558  * 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)
4559  * 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.
4560  *
4561  * \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.
4562  * \sa MEDCouplingUMesh::colinearize2D
4563  */
4564 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4565 {
4566   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4567     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4568   checkFullyDefined();
4569   const double *coords=getCoords()->getConstPointer();
4570   int nbOfCells=getNumberOfCells();
4571   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4572   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4573   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4574   int *workIndexOut=nodalConnecIndexOut->getPointer();
4575   *workIndexOut=0;
4576   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4577   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4578   std::set<INTERP_KERNEL::NormalizedCellType> types;
4579   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4580   isChanged->alloc(0,1);
4581   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4582     {
4583       int pos=nodalConnecOut->getNumberOfTuples();
4584       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4585         isChanged->pushBackSilent(i);
4586       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4587       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4588     }
4589   if(isChanged->empty())
4590     return 0;
4591   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4592   _types=types;
4593   return isChanged.retn();
4594 }
4595
4596 /*!
4597  * This method is \b NOT const because it can modify \a this.
4598  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4599  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4600  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4601  * \b 1 for translation and rotation around point of 'mesh1D'.
4602  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4603  */
4604 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4605 {
4606   checkFullyDefined();
4607   mesh1D->checkFullyDefined();
4608   if(!mesh1D->isContiguous1D())
4609     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4610   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4611     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4612   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4613     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4614   if(mesh1D->getMeshDimension()!=1)
4615     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4616   bool isQuad=false;
4617   if(isPresenceOfQuadratic())
4618     {
4619       if(mesh1D->isFullyQuadratic())
4620         isQuad=true;
4621       else
4622         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4623     }
4624   int oldNbOfNodes(getNumberOfNodes());
4625   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4626   switch(policy)
4627   {
4628     case 0:
4629       {
4630         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4631         break;
4632       }
4633     case 1:
4634       {
4635         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4636         break;
4637       }
4638     default:
4639       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4640   }
4641   setCoords(newCoords);
4642   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4643   updateTime();
4644   return ret.retn();
4645 }
4646
4647 /*!
4648  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4649  * If it is not the case an exception will be thrown.
4650  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4651  * intersection of plane defined by ('origin','vec').
4652  * This method has one in/out parameter : 'cut3DCurve'.
4653  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4654  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4655  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4656  * This method will throw an exception if \a this contains a non linear segment.
4657  */
4658 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4659 {
4660   checkFullyDefined();
4661   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4662     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4663   int ncells=getNumberOfCells();
4664   int nnodes=getNumberOfNodes();
4665   double vec2[3],vec3[3],vec4[3];
4666   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4667   if(normm<1e-6)
4668     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4669   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4670   const int *conn=_nodal_connec->getConstPointer();
4671   const int *connI=_nodal_connec_index->getConstPointer();
4672   const double *coo=_coords->getConstPointer();
4673   std::vector<double> addCoo;
4674   for(int i=0;i<ncells;i++)
4675     {
4676       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4677         {
4678           if(cut3DCurve[i]==-2)
4679             {
4680               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4681               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];
4682               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4683               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4684               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4685                 {
4686                   const double *st2=coo+3*st;
4687                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4688                   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]));
4689                   if(pos>eps && pos<1-eps)
4690                     {
4691                       int nNode=((int)addCoo.size())/3;
4692                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4693                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4694                       cut3DCurve[i]=nnodes+nNode;
4695                     }
4696                 }
4697             }
4698         }
4699       else
4700         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4701     }
4702   if(!addCoo.empty())
4703     {
4704       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4705       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4706       coo2->alloc(newNbOfNodes,3);
4707       double *tmp=coo2->getPointer();
4708       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4709       std::copy(addCoo.begin(),addCoo.end(),tmp);
4710       DataArrayDouble::SetArrayIn(coo2,_coords);
4711     }
4712 }
4713
4714 /*!
4715  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4716  * \param mesh1D is the input 1D mesh used for translation computation.
4717  * \return newCoords new coords filled by this method. 
4718  */
4719 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4720 {
4721   int oldNbOfNodes=getNumberOfNodes();
4722   int nbOf1DCells=mesh1D->getNumberOfCells();
4723   int spaceDim=getSpaceDimension();
4724   DataArrayDouble *ret=DataArrayDouble::New();
4725   std::vector<bool> isQuads;
4726   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4727   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4728   double *retPtr=ret->getPointer();
4729   const double *coords=getCoords()->getConstPointer();
4730   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4731   std::vector<int> v;
4732   std::vector<double> c;
4733   double vec[3];
4734   v.reserve(3);
4735   c.reserve(6);
4736   for(int i=0;i<nbOf1DCells;i++)
4737     {
4738       v.resize(0);
4739       mesh1D->getNodeIdsOfCell(i,v);
4740       c.resize(0);
4741       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4742       mesh1D->getCoordinatesOfNode(v[0],c);
4743       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4744       for(int j=0;j<oldNbOfNodes;j++)
4745         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4746       if(isQuad)
4747         {
4748           c.resize(0);
4749           mesh1D->getCoordinatesOfNode(v[1],c);
4750           mesh1D->getCoordinatesOfNode(v[0],c);
4751           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4752           for(int j=0;j<oldNbOfNodes;j++)
4753             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4754         }
4755     }
4756   ret->copyStringInfoFrom(*getCoords());
4757   return ret;
4758 }
4759
4760 /*!
4761  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4762  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4763  * \return newCoords new coords filled by this method. 
4764  */
4765 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4766 {
4767   if(mesh1D->getSpaceDimension()==2)
4768     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4769   if(mesh1D->getSpaceDimension()==3)
4770     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4771   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4772 }
4773
4774 /*!
4775  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4776  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4777  * \return newCoords new coords filled by this method. 
4778  */
4779 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4780 {
4781   if(isQuad)
4782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4783   int oldNbOfNodes=getNumberOfNodes();
4784   int nbOf1DCells=mesh1D->getNumberOfCells();
4785   if(nbOf1DCells<2)
4786     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4787   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4788   int nbOfLevsInVec=nbOf1DCells+1;
4789   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4790   double *retPtr=ret->getPointer();
4791   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4792   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4793   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4794   tmp->setCoords(tmp2);
4795   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4796   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4797   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4798   for(int i=1;i<nbOfLevsInVec;i++)
4799     {
4800       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4801       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4802       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4803       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4804       tmp->translate(vec);
4805       double tmp3[2],radius,alpha,alpha0;
4806       const double *p0=i+1<nbOfLevsInVec?begin:third;
4807       const double *p1=i+1<nbOfLevsInVec?end:begin;
4808       const double *p2=i+1<nbOfLevsInVec?third:end;
4809       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4810       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]);
4811       double angle=acos(cosangle/(radius*radius));
4812       tmp->rotate(end,0,angle);
4813       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4814     }
4815   return ret.retn();
4816 }
4817
4818 /*!
4819  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4820  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4821  * \return newCoords new coords filled by this method. 
4822  */
4823 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4824 {
4825   if(isQuad)
4826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4827   int oldNbOfNodes=getNumberOfNodes();
4828   int nbOf1DCells=mesh1D->getNumberOfCells();
4829   if(nbOf1DCells<2)
4830     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4831   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4832   int nbOfLevsInVec=nbOf1DCells+1;
4833   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4834   double *retPtr=ret->getPointer();
4835   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4836   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4837   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4838   tmp->setCoords(tmp2);
4839   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4840   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4841   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4842   for(int i=1;i<nbOfLevsInVec;i++)
4843     {
4844       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4845       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4846       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4847       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4848       tmp->translate(vec);
4849       double tmp3[2],radius,alpha,alpha0;
4850       const double *p0=i+1<nbOfLevsInVec?begin:third;
4851       const double *p1=i+1<nbOfLevsInVec?end:begin;
4852       const double *p2=i+1<nbOfLevsInVec?third:end;
4853       double vecPlane[3]={
4854         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4855         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4856         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4857       };
4858       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4859       if(norm>1.e-7)
4860         {
4861           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4862           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4863           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4864           double s2=norm2;
4865           double c2=cos(asin(s2));
4866           double m[3][3]={
4867             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4868             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4869             {-vec2[1]*s2, vec2[0]*s2, c2}
4870           };
4871           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]};
4872           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]};
4873           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]};
4874           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4875           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]);
4876           double angle=acos(cosangle/(radius*radius));
4877           tmp->rotate(end,vecPlane,angle);
4878         }
4879       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4880     }
4881   return ret.retn();
4882 }
4883
4884 /*!
4885  * This method is private because not easy to use for end user. This method is const contrary to
4886  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4887  * the coords sorted slice by slice.
4888  * \param isQuad specifies presence of quadratic cells.
4889  */
4890 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4891 {
4892   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4893   int nbOf2DCells(getNumberOfCells());
4894   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4895   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4896   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4898   newConnI->alloc(nbOf3DCells+1,1);
4899   int *newConnIPtr(newConnI->getPointer());
4900   *newConnIPtr++=0;
4901   std::vector<int> newc;
4902   for(int j=0;j<nbOf2DCells;j++)
4903     {
4904       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4905       *newConnIPtr++=(int)newc.size();
4906     }
4907   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4908   int *newConnPtr(newConn->getPointer());
4909   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4910   newConnIPtr=newConnI->getPointer();
4911   for(int iz=0;iz<nbOf1DCells;iz++)
4912     {
4913       if(iz!=0)
4914         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4915       const int *posOfTypeOfCell(newConnIPtr);
4916       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4917         {
4918           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4919           if(icell!=*posOfTypeOfCell)
4920             {
4921               if(*iter!=-1)
4922                 *newConnPtr=(*iter)+iz*deltaPerLev;
4923               else
4924                 *newConnPtr=-1;
4925             }
4926           else
4927             {
4928               *newConnPtr=*iter;
4929               posOfTypeOfCell++;
4930             }
4931         }
4932     }
4933   ret->setConnectivity(newConn,newConnI,true);
4934   ret->setCoords(getCoords());
4935   return ret;
4936 }
4937
4938 /*!
4939  * Checks if \a this mesh is constituted by only quadratic cells.
4940  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4941  *  \throw If the coordinates array is not set.
4942  *  \throw If the nodal connectivity of cells is not defined.
4943  */
4944 bool MEDCouplingUMesh::isFullyQuadratic() const
4945 {
4946   checkFullyDefined();
4947   bool ret=true;
4948   int nbOfCells=getNumberOfCells();
4949   for(int i=0;i<nbOfCells && ret;i++)
4950     {
4951       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4952       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4953       ret=cm.isQuadratic();
4954     }
4955   return ret;
4956 }
4957
4958 /*!
4959  * Checks if \a this mesh includes any quadratic cell.
4960  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4961  *  \throw If the coordinates array is not set.
4962  *  \throw If the nodal connectivity of cells is not defined.
4963  */
4964 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4965 {
4966   checkFullyDefined();
4967   bool ret=false;
4968   int nbOfCells=getNumberOfCells();
4969   for(int i=0;i<nbOfCells && !ret;i++)
4970     {
4971       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4972       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4973       ret=cm.isQuadratic();
4974     }
4975   return ret;
4976 }
4977
4978 /*!
4979  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4980  * this mesh, it remains unchanged.
4981  *  \throw If the coordinates array is not set.
4982  *  \throw If the nodal connectivity of cells is not defined.
4983  */
4984 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4985 {
4986   checkFullyDefined();
4987   int nbOfCells=getNumberOfCells();
4988   int delta=0;
4989   const int *iciptr=_nodal_connec_index->getConstPointer();
4990   for(int i=0;i<nbOfCells;i++)
4991     {
4992       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4993       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4994       if(cm.isQuadratic())
4995         {
4996           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4997           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4998           if(!cml.isDynamic())
4999             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5000           else
5001             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5002         }
5003     }
5004   if(delta==0)
5005     return ;
5006   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5007   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5008   const int *icptr=_nodal_connec->getConstPointer();
5009   newConn->alloc(getMeshLength()-delta,1);
5010   newConnI->alloc(nbOfCells+1,1);
5011   int *ocptr=newConn->getPointer();
5012   int *ociptr=newConnI->getPointer();
5013   *ociptr=0;
5014   _types.clear();
5015   for(int i=0;i<nbOfCells;i++,ociptr++)
5016     {
5017       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5018       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5019       if(!cm.isQuadratic())
5020         {
5021           _types.insert(type);
5022           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5023           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5024         }
5025       else
5026         {
5027           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5028           _types.insert(typel);
5029           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5030           int newNbOfNodes=cml.getNumberOfNodes();
5031           if(cml.isDynamic())
5032             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5033           *ocptr++=(int)typel;
5034           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5035           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5036         }
5037     }
5038   setConnectivity(newConn,newConnI,false);
5039 }
5040
5041 /*!
5042  * This method converts all linear cell in \a this to quadratic one.
5043  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5044  * 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)
5045  * 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.
5046  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5047  * end of the existing coordinates.
5048  * 
5049  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5050  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5051  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5052  * 
5053  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5054  *
5055  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5056  */
5057 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5058 {
5059   DataArrayInt *conn=0,*connI=0;
5060   DataArrayDouble *coords=0;
5061   std::set<INTERP_KERNEL::NormalizedCellType> types;
5062   checkFullyDefined();
5063   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5064   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5065   int meshDim=getMeshDimension();
5066   switch(conversionType)
5067   {
5068     case 0:
5069       switch(meshDim)
5070       {
5071         case 1:
5072           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5073           connSafe=conn; connISafe=connI; coordsSafe=coords;
5074           break;
5075         case 2:
5076           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5077           connSafe=conn; connISafe=connI; coordsSafe=coords;
5078           break;
5079         case 3:
5080           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5081           connSafe=conn; connISafe=connI; coordsSafe=coords;
5082           break;
5083         default:
5084           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5085       }
5086       break;
5087         case 1:
5088           {
5089             switch(meshDim)
5090             {
5091               case 1:
5092                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5093                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5094                 break;
5095               case 2:
5096                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5097                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5098                 break;
5099               case 3:
5100                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5101                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5102                 break;
5103               default:
5104                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5105             }
5106             break;
5107           }
5108         default:
5109           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5110   }
5111   setConnectivity(connSafe,connISafe,false);
5112   _types=types;
5113   setCoords(coordsSafe);
5114   return ret.retn();
5115 }
5116
5117 #if 0
5118 /*!
5119  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5120  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5121  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5122  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5123  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5124  * This method can be seen as the opposite method of colinearize2D.
5125  * 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
5126  * to avoid to modify the numbering of existing nodes.
5127  *
5128  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5129  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5130  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5131  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5132  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5133  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5134  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5135  *
5136  * \sa buildDescendingConnectivity2
5137  */
5138 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5139                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5140 {
5141   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5142     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5143   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5144   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5145     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5146   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5147     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5148   //DataArrayInt *out0(0),*outi0(0);
5149   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5150   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5151   //out0s=out0s->buildUnique(); out0s->sort(true);
5152 }
5153 #endif
5154
5155 /*!
5156  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5157  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5158  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5159  */
5160 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5161 {
5162   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5163   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5164   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5165   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5166   int nbOfCells=getNumberOfCells();
5167   int nbOfNodes=getNumberOfNodes();
5168   const int *cPtr=_nodal_connec->getConstPointer();
5169   const int *icPtr=_nodal_connec_index->getConstPointer();
5170   int lastVal=0,offset=nbOfNodes;
5171   for(int i=0;i<nbOfCells;i++,icPtr++)
5172     {
5173       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5174       if(type==INTERP_KERNEL::NORM_SEG2)
5175         {
5176           types.insert(INTERP_KERNEL::NORM_SEG3);
5177           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5178           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5179           newConn->pushBackSilent(offset++);
5180           lastVal+=4;
5181           newConnI->pushBackSilent(lastVal);
5182           ret->pushBackSilent(i);
5183         }
5184       else
5185         {
5186           types.insert(type);
5187           lastVal+=(icPtr[1]-icPtr[0]);
5188           newConnI->pushBackSilent(lastVal);
5189           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5190         }
5191     }
5192   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5193   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5194   return ret.retn();
5195 }
5196
5197 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
5198 {
5199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5200   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5202   //
5203   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5204   DataArrayInt *conn1D=0,*conn1DI=0;
5205   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5206   DataArrayDouble *coordsTmp=0;
5207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5208   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5210   const int *c1DPtr=conn1D->begin();
5211   const int *c1DIPtr=conn1DI->begin();
5212   int nbOfCells=getNumberOfCells();
5213   const int *cPtr=_nodal_connec->getConstPointer();
5214   const int *icPtr=_nodal_connec_index->getConstPointer();
5215   int lastVal=0;
5216   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5217     {
5218       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5219       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5220       if(!cm.isQuadratic())
5221         {
5222           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5223           types.insert(typ2); newConn->pushBackSilent(typ2);
5224           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5225           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5226             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5227           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5228           newConnI->pushBackSilent(lastVal);
5229           ret->pushBackSilent(i);
5230         }
5231       else
5232         {
5233           types.insert(typ);
5234           lastVal+=(icPtr[1]-icPtr[0]);
5235           newConnI->pushBackSilent(lastVal);
5236           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5237         }
5238     }
5239   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5240   return ret.retn();
5241 }
5242
5243 /*!
5244  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5245  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5246  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5247  */
5248 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5249 {
5250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5251   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5252   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5253 }
5254
5255 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5256 {
5257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5258   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5259   //
5260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5261   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5262   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5263   //
5264   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5265   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5266   DataArrayInt *conn1D=0,*conn1DI=0;
5267   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5268   DataArrayDouble *coordsTmp=0;
5269   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5270   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5272   const int *c1DPtr=conn1D->begin();
5273   const int *c1DIPtr=conn1DI->begin();
5274   int nbOfCells=getNumberOfCells();
5275   const int *cPtr=_nodal_connec->getConstPointer();
5276   const int *icPtr=_nodal_connec_index->getConstPointer();
5277   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5278   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5279     {
5280       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5281       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5282       if(!cm.isQuadratic())
5283         {
5284           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5285           types.insert(typ2); newConn->pushBackSilent(typ2);
5286           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5287           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5288             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5289           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5290           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5291           newConnI->pushBackSilent(lastVal);
5292           ret->pushBackSilent(i);
5293         }
5294       else
5295         {
5296           types.insert(typ);
5297           lastVal+=(icPtr[1]-icPtr[0]);
5298           newConnI->pushBackSilent(lastVal);
5299           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5300         }
5301     }
5302   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5303   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5304   return ret.retn();
5305 }
5306
5307 /*!
5308  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5309  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5310  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5311  */
5312 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5313 {
5314   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5315   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5316   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5317 }
5318
5319 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5320 {
5321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5322   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5324   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5325   //
5326   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5327   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5329   //
5330   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5331   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5332   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5333   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5334   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5337   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5339   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5340   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5341   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5342   int nbOfCells=getNumberOfCells();
5343   const int *cPtr=_nodal_connec->getConstPointer();
5344   const int *icPtr=_nodal_connec_index->getConstPointer();
5345   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5346   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5347     {
5348       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5349       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5350       if(!cm.isQuadratic())
5351         {
5352           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5353           if(typ2==INTERP_KERNEL::NORM_ERROR)
5354             {
5355               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5356               throw INTERP_KERNEL::Exception(oss.str().c_str());
5357             }
5358           types.insert(typ2); newConn->pushBackSilent(typ2);
5359           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5360           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5361             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5362           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5363             {
5364               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5365               int tmpPos=newConn->getNumberOfTuples();
5366               newConn->pushBackSilent(nodeId2);
5367               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5368             }
5369           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5370           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5371           newConnI->pushBackSilent(lastVal);
5372           ret->pushBackSilent(i);
5373         }
5374       else
5375         {
5376           types.insert(typ);
5377           lastVal+=(icPtr[1]-icPtr[0]);
5378           newConnI->pushBackSilent(lastVal);
5379           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5380         }
5381     }
5382   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5384   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5385   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5386   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5387   int *c=newConn->getPointer();
5388   const int *cI(newConnI->begin());
5389   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5390     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5391   offset=coordsTmp2Safe->getNumberOfTuples();
5392   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5393     c[cI[(*elt)+1]-1]+=offset;
5394   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5395   return ret.retn();
5396 }
5397
5398 /*!
5399  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5400  * so that the number of cells remains the same. Quadratic faces are converted to
5401  * polygons. This method works only for 2D meshes in
5402  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5403  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5404  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5405  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5406  *         a polylinized edge constituting the input polygon.
5407  *  \throw If the coordinates array is not set.
5408  *  \throw If the nodal connectivity of cells is not defined.
5409  *  \throw If \a this->getMeshDimension() != 2.
5410  *  \throw If \a this->getSpaceDimension() != 2.
5411  */
5412 void MEDCouplingUMesh::tessellate2D(double eps)
5413 {
5414   checkFullyDefined();
5415   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5416     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5417   double epsa=fabs(eps);
5418   if(epsa<std::numeric_limits<double>::min())
5419     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 !");
5420   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5422   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5423   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5424   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5425   revDesc1=0; revDescIndx1=0;
5426   mDesc->tessellate2DCurve(eps);
5427   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5428   setCoords(mDesc->getCoords());
5429 }
5430
5431 /*!
5432  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5433  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5434  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5435  *         a sub-divided edge.
5436  *  \throw If the coordinates array is not set.
5437  *  \throw If the nodal connectivity of cells is not defined.
5438  *  \throw If \a this->getMeshDimension() != 1.
5439  *  \throw If \a this->getSpaceDimension() != 2.
5440  */
5441 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5442 {
5443   checkFullyDefined();
5444   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5446   double epsa=fabs(eps);
5447   if(epsa<std::numeric_limits<double>::min())
5448     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 !");
5449   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5450   int nbCells=getNumberOfCells();
5451   int nbNodes=getNumberOfNodes();
5452   const int *conn=_nodal_connec->getConstPointer();
5453   const int *connI=_nodal_connec_index->getConstPointer();
5454   const double *coords=_coords->getConstPointer();
5455   std::vector<double> addCoo;
5456   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5458   newConnI->alloc(nbCells+1,1);
5459   int *newConnIPtr=newConnI->getPointer();
5460   *newConnIPtr=0;
5461   int tmp1[3];
5462   INTERP_KERNEL::Node *tmp2[3];
5463   std::set<INTERP_KERNEL::NormalizedCellType> types;
5464   for(int i=0;i<nbCells;i++,newConnIPtr++)
5465     {
5466       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5467       if(cm.isQuadratic())
5468         {//assert(connI[i+1]-connI[i]-1==3)
5469           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5470           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5471           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5472           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5473           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5474           if(eac)
5475             {
5476               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5477               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5478               delete eac;
5479               newConnIPtr[1]=(int)newConn.size();
5480             }
5481           else
5482             {
5483               types.insert(INTERP_KERNEL::NORM_SEG2);
5484               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5485               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5486               newConnIPtr[1]=newConnIPtr[0]+3;
5487             }
5488         }
5489       else
5490         {
5491           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5492           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5493           newConnIPtr[1]=newConnIPtr[0]+3;
5494         }
5495     }
5496   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5497     return ;
5498   _types=types;
5499   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5500   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5501   newConnArr->alloc((int)newConn.size(),1);
5502   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5503   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5504   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5505   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5506   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5507   std::copy(addCoo.begin(),addCoo.end(),work);
5508   DataArrayDouble::SetArrayIn(newCoords,_coords);
5509   updateTime();
5510 }
5511
5512 /*!
5513  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5514  * In addition, returns an array mapping new cells to old ones. <br>
5515  * This method typically increases the number of cells in \a this mesh
5516  * but the number of nodes remains \b unchanged.
5517  * That's why the 3D splitting policies
5518  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5519  *  \param [in] policy - specifies a pattern used for splitting.
5520  * The semantic of \a policy is:
5521  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5522  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5523  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5524  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5525  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5526  *          an id of old cell producing it. The caller is to delete this array using
5527  *         decrRef() as it is no more needed. 
5528  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5529  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5530  *          and \a this->getMeshDimension() != 3. 
5531  *  \throw If \a policy is not one of the four discussed above.
5532  *  \throw If the nodal connectivity of cells is not defined.
5533  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5534  */
5535 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5536 {
5537   switch(policy)
5538   {
5539     case 0:
5540       return simplexizePol0();
5541     case 1:
5542       return simplexizePol1();
5543     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5544         return simplexizePlanarFace5();
5545     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5546         return simplexizePlanarFace6();
5547     default:
5548       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)");
5549   }
5550 }
5551
5552 /*!
5553  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5554  * - 1D: INTERP_KERNEL::NORM_SEG2
5555  * - 2D: INTERP_KERNEL::NORM_TRI3
5556  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5557  *
5558  * This method is useful for users that need to use P1 field services as
5559  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5560  * All these methods need mesh support containing only simplex cells.
5561  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5562  *  \throw If the coordinates array is not set.
5563  *  \throw If the nodal connectivity of cells is not defined.
5564  *  \throw If \a this->getMeshDimension() < 1.
5565  */
5566 bool MEDCouplingUMesh::areOnlySimplexCells() const
5567 {
5568   checkFullyDefined();
5569   int mdim=getMeshDimension();
5570   if(mdim<1 || mdim>3)
5571     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5572   int nbCells=getNumberOfCells();
5573   const int *conn=_nodal_connec->getConstPointer();
5574   const int *connI=_nodal_connec_index->getConstPointer();
5575   for(int i=0;i<nbCells;i++)
5576     {
5577       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5578       if(!cm.isSimplex())
5579         return false;
5580     }
5581   return true;
5582 }
5583
5584 /*!
5585  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5586  */
5587 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5588 {
5589   checkConnectivityFullyDefined();
5590   if(getMeshDimension()!=2)
5591     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5592   int nbOfCells=getNumberOfCells();
5593   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5594   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5595   ret->alloc(nbOfCells+nbOfCutCells,1);
5596   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5597   int *retPt=ret->getPointer();
5598   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5599   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5600   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5601   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5602   int *pt=newConn->getPointer();
5603   int *ptI=newConnI->getPointer();
5604   ptI[0]=0;
5605   const int *oldc=_nodal_connec->getConstPointer();
5606   const int *ci=_nodal_connec_index->getConstPointer();
5607   for(int i=0;i<nbOfCells;i++,ci++)
5608     {
5609       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5610         {
5611           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5612             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5613           pt=std::copy(tmp,tmp+8,pt);
5614           ptI[1]=ptI[0]+4;
5615           ptI[2]=ptI[0]+8;
5616           *retPt++=i;
5617           *retPt++=i;
5618           ptI+=2;
5619         }
5620       else
5621         {
5622           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5623           ptI[1]=ptI[0]+ci[1]-ci[0];
5624           ptI++;
5625           *retPt++=i;
5626         }
5627     }
5628   _nodal_connec->decrRef();
5629   _nodal_connec=newConn.retn();
5630   _nodal_connec_index->decrRef();
5631   _nodal_connec_index=newConnI.retn();
5632   computeTypes();
5633   updateTime();
5634   return ret.retn();
5635 }
5636
5637 /*!
5638  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5639  */
5640 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5641 {
5642   checkConnectivityFullyDefined();
5643   if(getMeshDimension()!=2)
5644     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5645   int nbOfCells=getNumberOfCells();
5646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5647   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5648   ret->alloc(nbOfCells+nbOfCutCells,1);
5649   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5650   int *retPt=ret->getPointer();
5651   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5652   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5653   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5654   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5655   int *pt=newConn->getPointer();
5656   int *ptI=newConnI->getPointer();
5657   ptI[0]=0;
5658   const int *oldc=_nodal_connec->getConstPointer();
5659   const int *ci=_nodal_connec_index->getConstPointer();
5660   for(int i=0;i<nbOfCells;i++,ci++)
5661     {
5662       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5663         {
5664           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5665             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5666           pt=std::copy(tmp,tmp+8,pt);
5667           ptI[1]=ptI[0]+4;
5668           ptI[2]=ptI[0]+8;
5669           *retPt++=i;
5670           *retPt++=i;
5671           ptI+=2;
5672         }
5673       else
5674         {
5675           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5676           ptI[1]=ptI[0]+ci[1]-ci[0];
5677           ptI++;
5678           *retPt++=i;
5679         }
5680     }
5681   _nodal_connec->decrRef();
5682   _nodal_connec=newConn.retn();
5683   _nodal_connec_index->decrRef();
5684   _nodal_connec_index=newConnI.retn();
5685   computeTypes();
5686   updateTime();
5687   return ret.retn();
5688 }
5689
5690 /*!
5691  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5692  */
5693 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5694 {
5695   checkConnectivityFullyDefined();
5696   if(getMeshDimension()!=3)
5697     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5698   int nbOfCells=getNumberOfCells();
5699   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5700   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5701   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5702   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5703   int *retPt=ret->getPointer();
5704   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5706   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5707   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5708   int *pt=newConn->getPointer();
5709   int *ptI=newConnI->getPointer();
5710   ptI[0]=0;
5711   const int *oldc=_nodal_connec->getConstPointer();
5712   const int *ci=_nodal_connec_index->getConstPointer();
5713   for(int i=0;i<nbOfCells;i++,ci++)
5714     {
5715       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5716         {
5717           for(int j=0;j<5;j++,pt+=5,ptI++)
5718             {
5719               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5720               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];
5721               *retPt++=i;
5722               ptI[1]=ptI[0]+5;
5723             }
5724         }
5725       else
5726         {
5727           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5728           ptI[1]=ptI[0]+ci[1]-ci[0];
5729           ptI++;
5730           *retPt++=i;
5731         }
5732     }
5733   _nodal_connec->decrRef();
5734   _nodal_connec=newConn.retn();
5735   _nodal_connec_index->decrRef();
5736   _nodal_connec_index=newConnI.retn();
5737   computeTypes();
5738   updateTime();
5739   return ret.retn();
5740 }
5741
5742 /*!
5743  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5744  */
5745 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5746 {
5747   checkConnectivityFullyDefined();
5748   if(getMeshDimension()!=3)
5749     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5750   int nbOfCells=getNumberOfCells();
5751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5752   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5753   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5754   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5755   int *retPt=ret->getPointer();
5756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5758   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5759   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5760   int *pt=newConn->getPointer();
5761   int *ptI=newConnI->getPointer();
5762   ptI[0]=0;
5763   const int *oldc=_nodal_connec->getConstPointer();
5764   const int *ci=_nodal_connec_index->getConstPointer();
5765   for(int i=0;i<nbOfCells;i++,ci++)
5766     {
5767       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5768         {
5769           for(int j=0;j<6;j++,pt+=5,ptI++)
5770             {
5771               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5772               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];
5773               *retPt++=i;
5774               ptI[1]=ptI[0]+5;
5775             }
5776         }
5777       else
5778         {
5779           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5780           ptI[1]=ptI[0]+ci[1]-ci[0];
5781           ptI++;
5782           *retPt++=i;
5783         }
5784     }
5785   _nodal_connec->decrRef();
5786   _nodal_connec=newConn.retn();
5787   _nodal_connec_index->decrRef();
5788   _nodal_connec_index=newConnI.retn();
5789   computeTypes();
5790   updateTime();
5791   return ret.retn();
5792 }
5793
5794 /*!
5795  * 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.
5796  * This method completly ignore coordinates.
5797  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5798  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5799  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5800  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5801  */
5802 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5803 {
5804   checkFullyDefined();
5805   if(getMeshDimension()!=2)
5806     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5807   int nbOfCells=getNumberOfCells();
5808   int *connI=_nodal_connec_index->getPointer();
5809   int newConnLgth=0;
5810   for(int i=0;i<nbOfCells;i++,connI++)
5811     {
5812       int offset=descIndex[i];
5813       int nbOfEdges=descIndex[i+1]-offset;
5814       //
5815       bool ddirect=desc[offset+nbOfEdges-1]>0;
5816       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5817       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5818       for(int j=0;j<nbOfEdges;j++)
5819         {
5820           bool direct=desc[offset+j]>0;
5821           int edgeId=std::abs(desc[offset+j])-1;
5822           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5823             {
5824               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5825               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5826               int ref2=direct?id1:id2;
5827               if(ref==ref2)
5828                 {
5829                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5830                   newConnLgth+=nbOfSubNodes-1;
5831                   ref=direct?id2:id1;
5832                 }
5833               else
5834                 {
5835                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5836                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5837                 }
5838             }
5839           else
5840             {
5841               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5842             }
5843         }
5844       newConnLgth++;//+1 is for cell type
5845       connI[1]=newConnLgth;
5846     }
5847   //
5848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5849   newConn->alloc(newConnLgth,1);
5850   int *work=newConn->getPointer();
5851   for(int i=0;i<nbOfCells;i++)
5852     {
5853       *work++=INTERP_KERNEL::NORM_POLYGON;
5854       int offset=descIndex[i];
5855       int nbOfEdges=descIndex[i+1]-offset;
5856       for(int j=0;j<nbOfEdges;j++)
5857         {
5858           bool direct=desc[offset+j]>0;
5859           int edgeId=std::abs(desc[offset+j])-1;
5860           if(direct)
5861             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5862           else
5863             {
5864               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5865               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5866               work=std::copy(it,it+nbOfSubNodes-1,work);
5867             }
5868         }
5869     }
5870   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5871   _types.clear();
5872   if(nbOfCells>0)
5873     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5874 }
5875
5876 /*!
5877  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5878  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5879  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5880  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5881  * so it can be useful to call mergeNodes() before calling this method.
5882  *  \throw If \a this->getMeshDimension() <= 1.
5883  *  \throw If the coordinates array is not set.
5884  *  \throw If the nodal connectivity of cells is not defined.
5885  */
5886 void MEDCouplingUMesh::convertDegeneratedCells()
5887 {
5888   checkFullyDefined();
5889   if(getMeshDimension()<=1)
5890     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5891   int nbOfCells=getNumberOfCells();
5892   if(nbOfCells<1)
5893     return ;
5894   int initMeshLgth=getMeshLength();
5895   int *conn=_nodal_connec->getPointer();
5896   int *index=_nodal_connec_index->getPointer();
5897   int posOfCurCell=0;
5898   int newPos=0;
5899   int lgthOfCurCell;
5900   for(int i=0;i<nbOfCells;i++)
5901     {
5902       lgthOfCurCell=index[i+1]-posOfCurCell;
5903       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5904       int newLgth;
5905       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5906                                                                                                      conn+newPos+1,newLgth);
5907       conn[newPos]=newType;
5908       newPos+=newLgth+1;
5909       posOfCurCell=index[i+1];
5910       index[i+1]=newPos;
5911     }
5912   if(newPos!=initMeshLgth)
5913     _nodal_connec->reAlloc(newPos);
5914   computeTypes();
5915 }
5916
5917 /*!
5918  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5919  * A cell is considered to be oriented correctly if an angle between its
5920  * normal vector and a given vector is less than \c PI / \c 2.
5921  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5922  *         cells. 
5923  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5924  *         checked.
5925  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5926  *         is not cleared before filling in.
5927  *  \throw If \a this->getMeshDimension() != 2.
5928  *  \throw If \a this->getSpaceDimension() != 3.
5929  *
5930  *  \if ENABLE_EXAMPLES
5931  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5932  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5933  *  \endif
5934  */
5935 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5936 {
5937   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5938     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5939   int nbOfCells=getNumberOfCells();
5940   const int *conn=_nodal_connec->getConstPointer();
5941   const int *connI=_nodal_connec_index->getConstPointer();
5942   const double *coordsPtr=_coords->getConstPointer();
5943   for(int i=0;i<nbOfCells;i++)
5944     {
5945       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5946       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5947         {
5948           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5949           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5950             cells.push_back(i);
5951         }
5952     }
5953 }
5954
5955 /*!
5956  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5957  * considered to be oriented correctly if an angle between its normal vector and a
5958  * given vector is less than \c PI / \c 2. 
5959  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5960  *         cells. 
5961  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5962  *         checked.
5963  *  \throw If \a this->getMeshDimension() != 2.
5964  *  \throw If \a this->getSpaceDimension() != 3.
5965  *
5966  *  \if ENABLE_EXAMPLES
5967  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5968  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5969  *  \endif
5970  *
5971  *  \sa changeOrientationOfCells
5972  */
5973 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5974 {
5975   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5976     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5977   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5978   const int *connI(_nodal_connec_index->getConstPointer());
5979   const double *coordsPtr(_coords->getConstPointer());
5980   bool isModified(false);
5981   for(int i=0;i<nbOfCells;i++)
5982     {
5983       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5984       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5985         {
5986           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5987           bool isQuadratic(cm.isQuadratic());
5988           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5989             {
5990               isModified=true;
5991               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
5992             }
5993         }
5994     }
5995   if(isModified)
5996     _nodal_connec->declareAsNew();
5997   updateTime();
5998 }
5999
6000 /*!
6001  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6002  *
6003  * \sa orientCorrectly2DCells
6004  */
6005 void MEDCouplingUMesh::changeOrientationOfCells()
6006 {
6007   int mdim(getMeshDimension());
6008   if(mdim!=2 && mdim!=1)
6009     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6010   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6011   const int *connI(_nodal_connec_index->getConstPointer());
6012   if(mdim==2)
6013     {//2D
6014       for(int i=0;i<nbOfCells;i++)
6015         {
6016           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6017           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6018           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6019         }
6020     }
6021   else
6022     {//1D
6023       for(int i=0;i<nbOfCells;i++)
6024         {
6025           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6026           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6027           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6028         }
6029     }
6030 }
6031
6032 /*!
6033  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6034  * oriented facets. The normal vector of the facet should point out of the cell.
6035  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6036  *         is not cleared before filling in.
6037  *  \throw If \a this->getMeshDimension() != 3.
6038  *  \throw If \a this->getSpaceDimension() != 3.
6039  *  \throw If the coordinates array is not set.
6040  *  \throw If the nodal connectivity of cells is not defined.
6041  *
6042  *  \if ENABLE_EXAMPLES
6043  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6044  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6045  *  \endif
6046  */
6047 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6048 {
6049   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6050     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6051   int nbOfCells=getNumberOfCells();
6052   const int *conn=_nodal_connec->getConstPointer();
6053   const int *connI=_nodal_connec_index->getConstPointer();
6054   const double *coordsPtr=_coords->getConstPointer();
6055   for(int i=0;i<nbOfCells;i++)
6056     {
6057       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6058       if(type==INTERP_KERNEL::NORM_POLYHED)
6059         {
6060           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6061             cells.push_back(i);
6062         }
6063     }
6064 }
6065
6066 /*!
6067  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6068  * out of the cell. 
6069  *  \throw If \a this->getMeshDimension() != 3.
6070  *  \throw If \a this->getSpaceDimension() != 3.
6071  *  \throw If the coordinates array is not set.
6072  *  \throw If the nodal connectivity of cells is not defined.
6073  *  \throw If the reparation fails.
6074  *
6075  *  \if ENABLE_EXAMPLES
6076  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6077  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6078  *  \endif
6079  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6080  */
6081 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6082 {
6083   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6084     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6085   int nbOfCells=getNumberOfCells();
6086   int *conn=_nodal_connec->getPointer();
6087   const int *connI=_nodal_connec_index->getConstPointer();
6088   const double *coordsPtr=_coords->getConstPointer();
6089   for(int i=0;i<nbOfCells;i++)
6090     {
6091       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6092       if(type==INTERP_KERNEL::NORM_POLYHED)
6093         {
6094           try
6095           {
6096               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6097                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6098           }
6099           catch(INTERP_KERNEL::Exception& e)
6100           {
6101               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6102               throw INTERP_KERNEL::Exception(oss.str().c_str());
6103           }
6104         }
6105     }
6106   updateTime();
6107 }
6108
6109 /*!
6110  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6111  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6112  * according to which the first facet of the cell should be oriented to have the normal vector
6113  * pointing out of cell.
6114  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6115  *         cells. The caller is to delete this array using decrRef() as it is no more
6116  *         needed. 
6117  *  \throw If \a this->getMeshDimension() != 3.
6118  *  \throw If \a this->getSpaceDimension() != 3.
6119  *  \throw If the coordinates array is not set.
6120  *  \throw If the nodal connectivity of cells is not defined.
6121  *
6122  *  \if ENABLE_EXAMPLES
6123  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6124  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6125  *  \endif
6126  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6127  */
6128 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6129 {
6130   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6131   if(getMeshDimension()!=3)
6132     throw INTERP_KERNEL::Exception(msg);
6133   int spaceDim=getSpaceDimension();
6134   if(spaceDim!=3)
6135     throw INTERP_KERNEL::Exception(msg);
6136   //
6137   int nbOfCells=getNumberOfCells();
6138   int *conn=_nodal_connec->getPointer();
6139   const int *connI=_nodal_connec_index->getConstPointer();
6140   const double *coo=getCoords()->getConstPointer();
6141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6142   for(int i=0;i<nbOfCells;i++)
6143     {
6144       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6145       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6146         {
6147           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6148             {
6149               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6150               cells->pushBackSilent(i);
6151             }
6152         }
6153     }
6154   return cells.retn();
6155 }
6156
6157 /*!
6158  * This method is a faster method to correct orientation of all 3D cells in \a this.
6159  * 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.
6160  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6161  * 
6162  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6163  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6164  */
6165 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6166 {
6167   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6168     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6169   int nbOfCells=getNumberOfCells();
6170   int *conn=_nodal_connec->getPointer();
6171   const int *connI=_nodal_connec_index->getConstPointer();
6172   const double *coordsPtr=_coords->getConstPointer();
6173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6174   for(int i=0;i<nbOfCells;i++)
6175     {
6176       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6177       switch(type)
6178       {
6179         case INTERP_KERNEL::NORM_TETRA4:
6180           {
6181             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6182               {
6183                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6184                 ret->pushBackSilent(i);
6185               }
6186             break;
6187           }
6188         case INTERP_KERNEL::NORM_PYRA5:
6189           {
6190             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6191               {
6192                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6193                 ret->pushBackSilent(i);
6194               }
6195             break;
6196           }
6197         case INTERP_KERNEL::NORM_PENTA6:
6198         case INTERP_KERNEL::NORM_HEXA8:
6199         case INTERP_KERNEL::NORM_HEXGP12:
6200           {
6201             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6202               {
6203                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6204                 ret->pushBackSilent(i);
6205               }
6206             break;
6207           }
6208         case INTERP_KERNEL::NORM_POLYHED:
6209           {
6210             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6211               {
6212                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6213                 ret->pushBackSilent(i);
6214               }
6215             break;
6216           }
6217         default:
6218           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 !");
6219       }
6220     }
6221   updateTime();
6222   return ret.retn();
6223 }
6224
6225 /*!
6226  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6227  * If it is not the case an exception will be thrown.
6228  * This method is fast because the first cell of \a this is used to compute the plane.
6229  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6230  * \param pos output of size at least 3 used to store a point owned of searched plane.
6231  */
6232 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6233 {
6234   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6235     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6236   const int *conn=_nodal_connec->getConstPointer();
6237   const int *connI=_nodal_connec_index->getConstPointer();
6238   const double *coordsPtr=_coords->getConstPointer();
6239   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6240   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6241 }
6242
6243 /*!
6244  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6245  * cells. Currently cells of the following types are treated:
6246  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6247  * For a cell of other type an exception is thrown.
6248  * Space dimension of a 2D mesh can be either 2 or 3.
6249  * The Edge Ratio of a cell \f$t\f$ is: 
6250  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6251  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6252  *  the smallest edge lengths of \f$t\f$.
6253  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6254  *          cells and one time, lying on \a this mesh. The caller is to delete this
6255  *          field using decrRef() as it is no more needed. 
6256  *  \throw If the coordinates array is not set.
6257  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6258  *  \throw If the connectivity data array has more than one component.
6259  *  \throw If the connectivity data array has a named component.
6260  *  \throw If the connectivity index data array has more than one component.
6261  *  \throw If the connectivity index data array has a named component.
6262  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6263  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6264  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6265  */
6266 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6267 {
6268   checkCoherency();
6269   int spaceDim=getSpaceDimension();
6270   int meshDim=getMeshDimension();
6271   if(spaceDim!=2 && spaceDim!=3)
6272     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6273   if(meshDim!=2 && meshDim!=3)
6274     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6275   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6276   ret->setMesh(this);
6277   int nbOfCells=getNumberOfCells();
6278   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6279   arr->alloc(nbOfCells,1);
6280   double *pt=arr->getPointer();
6281   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6282   const int *conn=_nodal_connec->getConstPointer();
6283   const int *connI=_nodal_connec_index->getConstPointer();
6284   const double *coo=_coords->getConstPointer();
6285   double tmp[12];
6286   for(int i=0;i<nbOfCells;i++,pt++)
6287     {
6288       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6289       switch(t)
6290       {
6291         case INTERP_KERNEL::NORM_TRI3:
6292           {
6293             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6294             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6295             break;
6296           }
6297         case INTERP_KERNEL::NORM_QUAD4:
6298           {
6299             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6300             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6301             break;
6302           }
6303         case INTERP_KERNEL::NORM_TETRA4:
6304           {
6305             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6306             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6307             break;
6308           }
6309         default:
6310           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6311       }
6312       conn+=connI[i+1]-connI[i];
6313     }
6314   ret->setName("EdgeRatio");
6315   ret->synchronizeTimeWithSupport();
6316   return ret.retn();
6317 }
6318
6319 /*!
6320  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6321  * cells. Currently cells of the following types are treated:
6322  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6323  * For a cell of other type an exception is thrown.
6324  * Space dimension of a 2D mesh can be either 2 or 3.
6325  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6326  *          cells and one time, lying on \a this mesh. The caller is to delete this
6327  *          field using decrRef() as it is no more needed. 
6328  *  \throw If the coordinates array is not set.
6329  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6330  *  \throw If the connectivity data array has more than one component.
6331  *  \throw If the connectivity data array has a named component.
6332  *  \throw If the connectivity index data array has more than one component.
6333  *  \throw If the connectivity index data array has a named component.
6334  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6335  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6336  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6337  */
6338 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6339 {
6340   checkCoherency();
6341   int spaceDim=getSpaceDimension();
6342   int meshDim=getMeshDimension();
6343   if(spaceDim!=2 && spaceDim!=3)
6344     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6345   if(meshDim!=2 && meshDim!=3)
6346     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6348   ret->setMesh(this);
6349   int nbOfCells=getNumberOfCells();
6350   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6351   arr->alloc(nbOfCells,1);
6352   double *pt=arr->getPointer();
6353   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6354   const int *conn=_nodal_connec->getConstPointer();
6355   const int *connI=_nodal_connec_index->getConstPointer();
6356   const double *coo=_coords->getConstPointer();
6357   double tmp[12];
6358   for(int i=0;i<nbOfCells;i++,pt++)
6359     {
6360       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6361       switch(t)
6362       {
6363         case INTERP_KERNEL::NORM_TRI3:
6364           {
6365             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6366             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6367             break;
6368           }
6369         case INTERP_KERNEL::NORM_QUAD4:
6370           {
6371             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6372             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6373             break;
6374           }
6375         case INTERP_KERNEL::NORM_TETRA4:
6376           {
6377             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6378             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6379             break;
6380           }
6381         default:
6382           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6383       }
6384       conn+=connI[i+1]-connI[i];
6385     }
6386   ret->setName("AspectRatio");
6387   ret->synchronizeTimeWithSupport();
6388   return ret.retn();
6389 }
6390
6391 /*!
6392  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6393  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6394  * treated: INTERP_KERNEL::NORM_QUAD4.
6395  * For a cell of other type an exception is thrown.
6396  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6397  *          cells and one time, lying on \a this mesh. The caller is to delete this
6398  *          field using decrRef() as it is no more needed. 
6399  *  \throw If the coordinates array is not set.
6400  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6401  *  \throw If the connectivity data array has more than one component.
6402  *  \throw If the connectivity data array has a named component.
6403  *  \throw If the connectivity index data array has more than one component.
6404  *  \throw If the connectivity index data array has a named component.
6405  *  \throw If \a this->getMeshDimension() != 2.
6406  *  \throw If \a this->getSpaceDimension() != 3.
6407  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6408  */
6409 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6410 {
6411   checkCoherency();
6412   int spaceDim=getSpaceDimension();
6413   int meshDim=getMeshDimension();
6414   if(spaceDim!=3)
6415     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6416   if(meshDim!=2)
6417     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6418   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6419   ret->setMesh(this);
6420   int nbOfCells=getNumberOfCells();
6421   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6422   arr->alloc(nbOfCells,1);
6423   double *pt=arr->getPointer();
6424   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6425   const int *conn=_nodal_connec->getConstPointer();
6426   const int *connI=_nodal_connec_index->getConstPointer();
6427   const double *coo=_coords->getConstPointer();
6428   double tmp[12];
6429   for(int i=0;i<nbOfCells;i++,pt++)
6430     {
6431       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6432       switch(t)
6433       {
6434         case INTERP_KERNEL::NORM_QUAD4:
6435           {
6436             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6437             *pt=INTERP_KERNEL::quadWarp(tmp);
6438             break;
6439           }
6440         default:
6441           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6442       }
6443       conn+=connI[i+1]-connI[i];
6444     }
6445   ret->setName("Warp");
6446   ret->synchronizeTimeWithSupport();
6447   return ret.retn();
6448 }
6449
6450
6451 /*!
6452  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6453  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6454  * treated: INTERP_KERNEL::NORM_QUAD4.
6455  * For a cell of other type an exception is thrown.
6456  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6457  *          cells and one time, lying on \a this mesh. The caller is to delete this
6458  *          field using decrRef() as it is no more needed. 
6459  *  \throw If the coordinates array is not set.
6460  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6461  *  \throw If the connectivity data array has more than one component.
6462  *  \throw If the connectivity data array has a named component.
6463  *  \throw If the connectivity index data array has more than one component.
6464  *  \throw If the connectivity index data array has a named component.
6465  *  \throw If \a this->getMeshDimension() != 2.
6466  *  \throw If \a this->getSpaceDimension() != 3.
6467  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6468  */
6469 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6470 {
6471   checkCoherency();
6472   int spaceDim=getSpaceDimension();
6473   int meshDim=getMeshDimension();
6474   if(spaceDim!=3)
6475     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6476   if(meshDim!=2)
6477     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6478   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6479   ret->setMesh(this);
6480   int nbOfCells=getNumberOfCells();
6481   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6482   arr->alloc(nbOfCells,1);
6483   double *pt=arr->getPointer();
6484   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6485   const int *conn=_nodal_connec->getConstPointer();
6486   const int *connI=_nodal_connec_index->getConstPointer();
6487   const double *coo=_coords->getConstPointer();
6488   double tmp[12];
6489   for(int i=0;i<nbOfCells;i++,pt++)
6490     {
6491       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6492       switch(t)
6493       {
6494         case INTERP_KERNEL::NORM_QUAD4:
6495           {
6496             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6497             *pt=INTERP_KERNEL::quadSkew(tmp);
6498             break;
6499           }
6500         default:
6501           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6502       }
6503       conn+=connI[i+1]-connI[i];
6504     }
6505   ret->setName("Skew");
6506   ret->synchronizeTimeWithSupport();
6507   return ret.retn();
6508 }
6509
6510 /*!
6511  * Returns the cell field giving for each cell in \a this its diameter. Diameter means the max length of all possible SEG2 in the cell.
6512  *
6513  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6514  *
6515  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6516  */
6517 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6518 {
6519   checkCoherency();
6520   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6521   ret->setMesh(this);
6522   std::set<INTERP_KERNEL::NormalizedCellType> types;
6523   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6524   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6525   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6526   arr->alloc(nbCells,1);
6527   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6528     {
6529       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6530       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6531       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6532     }
6533   ret->setArray(arr);
6534   ret->setName("Diameter");
6535   return ret.retn();
6536 }
6537
6538 /*!
6539  * This method aggregate the bbox of each cell and put it into bbox parameter.
6540  * 
6541  * \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)
6542  *                         For all other cases this input parameter is ignored.
6543  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6544  * 
6545  * \throw If \a this is not fully set (coordinates and connectivity).
6546  * \throw If a cell in \a this has no valid nodeId.
6547  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6548  */
6549 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6550 {
6551   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6552   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.
6553     return getBoundingBoxForBBTreeFast();
6554   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6555     {
6556       bool presenceOfQuadratic(false);
6557       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6558         {
6559           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6560           if(cm.isQuadratic())
6561             presenceOfQuadratic=true;
6562         }
6563       if(!presenceOfQuadratic)
6564         return getBoundingBoxForBBTreeFast();
6565       if(mDim==2 && sDim==2)
6566         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6567       else
6568         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6569     }
6570   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) !");
6571 }
6572
6573 /*!
6574  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6575  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6576  * 
6577  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6578  * 
6579  * \throw If \a this is not fully set (coordinates and connectivity).
6580  * \throw If a cell in \a this has no valid nodeId.
6581  */
6582 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6583 {
6584   checkFullyDefined();
6585   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6586   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6587   double *bbox(ret->getPointer());
6588   for(int i=0;i<nbOfCells*spaceDim;i++)
6589     {
6590       bbox[2*i]=std::numeric_limits<double>::max();
6591       bbox[2*i+1]=-std::numeric_limits<double>::max();
6592     }
6593   const double *coordsPtr(_coords->getConstPointer());
6594   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6595   for(int i=0;i<nbOfCells;i++)
6596     {
6597       int offset=connI[i]+1;
6598       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6599       for(int j=0;j<nbOfNodesForCell;j++)
6600         {
6601           int nodeId=conn[offset+j];
6602           if(nodeId>=0 && nodeId<nbOfNodes)
6603             {
6604               for(int k=0;k<spaceDim;k++)
6605                 {
6606                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6607                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6608                 }
6609               kk++;
6610             }
6611         }
6612       if(kk==0)
6613         {
6614           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6615           throw INTERP_KERNEL::Exception(oss.str().c_str());
6616         }
6617     }
6618   return ret.retn();
6619 }
6620
6621 /*!
6622  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6623  * useful for 2D meshes having quadratic cells
6624  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6625  * the two extremities of the arc of circle).
6626  * 
6627  * \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)
6628  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6629  * \throw If \a this is not fully defined.
6630  * \throw If \a this is not a mesh with meshDimension equal to 2.
6631  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6632  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6633  */
6634 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6635 {
6636   checkFullyDefined();
6637   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6638   if(spaceDim!=2 || mDim!=2)
6639     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!");
6640   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6641   double *bbox(ret->getPointer());
6642   const double *coords(_coords->getConstPointer());
6643   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6644   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6645     {
6646       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6647       int sz(connI[1]-connI[0]-1);
6648       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6649       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6650       INTERP_KERNEL::QuadraticPolygon *pol(0);
6651       for(int j=0;j<sz;j++)
6652         {
6653           int nodeId(conn[*connI+1+j]);
6654           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6655         }
6656       if(!cm.isQuadratic())
6657         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6658       else
6659         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6660       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6661       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6662     }
6663   return ret.retn();
6664 }
6665
6666 /*!
6667  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6668  * useful for 2D meshes having quadratic cells
6669  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6670  * the two extremities of the arc of circle).
6671  * 
6672  * \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)
6673  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6674  * \throw If \a this is not fully defined.
6675  * \throw If \a this is not a mesh with meshDimension equal to 1.
6676  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6677  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6678  */
6679 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6680 {
6681   checkFullyDefined();
6682   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6683   if(spaceDim!=2 || mDim!=1)
6684     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!");
6685   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6686   double *bbox(ret->getPointer());
6687   const double *coords(_coords->getConstPointer());
6688   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6689   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6690     {
6691       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6692       int sz(connI[1]-connI[0]-1);
6693       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6694       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6695       INTERP_KERNEL::Edge *edge(0);
6696       for(int j=0;j<sz;j++)
6697         {
6698           int nodeId(conn[*connI+1+j]);
6699           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6700         }
6701       if(!cm.isQuadratic())
6702         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6703       else
6704         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6705       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6706       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6707     }
6708   return ret.retn();
6709 }
6710
6711 /// @cond INTERNAL
6712
6713 namespace ParaMEDMEMImpl
6714 {
6715   class ConnReader
6716   {
6717   public:
6718     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6719     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6720   private:
6721     const int *_conn;
6722     int _val;
6723   };
6724
6725   class ConnReader2
6726   {
6727   public:
6728     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6729     bool operator() (const int& pos) { return _conn[pos]==_val; }
6730   private:
6731     const int *_conn;
6732     int _val;
6733   };
6734 }
6735
6736 /// @endcond
6737
6738 /*!
6739  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6740  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6741  * \a this is composed in cell types.
6742  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6743  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6744  * This parameter is kept only for compatibility with other methode listed above.
6745  */
6746 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6747 {
6748   checkConnectivityFullyDefined();
6749   const int *conn=_nodal_connec->getConstPointer();
6750   const int *connI=_nodal_connec_index->getConstPointer();
6751   const int *work=connI;
6752   int nbOfCells=getNumberOfCells();
6753   std::size_t n=getAllGeoTypes().size();
6754   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6755   std::set<INTERP_KERNEL::NormalizedCellType> types;
6756   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6757     {
6758       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6759       if(types.find(typ)!=types.end())
6760         {
6761           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6762           oss << " is not contiguous !";
6763           throw INTERP_KERNEL::Exception(oss.str().c_str());
6764         }
6765       types.insert(typ);
6766       ret[3*i]=typ;
6767       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6768       ret[3*i+1]=(int)std::distance(work,work2);
6769       work=work2;
6770     }
6771   return ret;
6772 }
6773
6774 /*!
6775  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6776  * only for types cell, type node is not managed.
6777  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6778  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6779  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6780  * If 2 or more same geometric type is in \a code and exception is thrown too.
6781  *
6782  * This method firstly checks
6783  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6784  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6785  * an exception is thrown too.
6786  * 
6787  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6788  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6789  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6790  */
6791 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6792 {
6793   if(code.empty())
6794     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6795   std::size_t sz=code.size();
6796   std::size_t n=sz/3;
6797   if(sz%3!=0)
6798     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6799   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6800   int nb=0;
6801   bool isNoPflUsed=true;
6802   for(std::size_t i=0;i<n;i++)
6803     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6804       {
6805         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6806         nb+=code[3*i+1];
6807         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6808           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6809         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6810       }
6811   if(types.size()!=n)
6812     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6813   if(isNoPflUsed)
6814     {
6815       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6816         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6817       if(types.size()==_types.size())
6818         return 0;
6819     }
6820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6821   ret->alloc(nb,1);
6822   int *retPtr=ret->getPointer();
6823   const int *connI=_nodal_connec_index->getConstPointer();
6824   const int *conn=_nodal_connec->getConstPointer();
6825   int nbOfCells=getNumberOfCells();
6826   const int *i=connI;
6827   int kk=0;
6828   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6829     {
6830       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6831       int offset=(int)std::distance(connI,i);
6832       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6833       int nbOfCellsOfCurType=(int)std::distance(i,j);
6834       if(code[3*kk+2]==-1)
6835         for(int k=0;k<nbOfCellsOfCurType;k++)
6836           *retPtr++=k+offset;
6837       else
6838         {
6839           int idInIdsPerType=code[3*kk+2];
6840           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6841             {
6842               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6843               if(zePfl)
6844                 {
6845                   zePfl->checkAllocated();
6846                   if(zePfl->getNumberOfComponents()==1)
6847                     {
6848                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6849                         {
6850                           if(*k>=0 && *k<nbOfCellsOfCurType)
6851                             *retPtr=(*k)+offset;
6852                           else
6853                             {
6854                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6855                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6856                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6857                             }
6858                         }
6859                     }
6860                   else
6861                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6862                 }
6863               else
6864                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6865             }
6866           else
6867             {
6868               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6869               oss << " should be in [0," << idsPerType.size() << ") !";
6870               throw INTERP_KERNEL::Exception(oss.str().c_str());
6871             }
6872         }
6873       i=j;
6874     }
6875   return ret.retn();
6876 }
6877
6878 /*!
6879  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6880  * 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.
6881  * 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.
6882  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6883  * 
6884  * \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.
6885  * \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,
6886  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6887  * \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.
6888  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6889  * \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
6890  */
6891 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6892 {
6893   if(!profile)
6894     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6895   if(profile->getNumberOfComponents()!=1)
6896     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6897   checkConnectivityFullyDefined();
6898   const int *conn=_nodal_connec->getConstPointer();
6899   const int *connI=_nodal_connec_index->getConstPointer();
6900   int nbOfCells=getNumberOfCells();
6901   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6902   std::vector<int> typeRangeVals(1);
6903   for(const int *i=connI;i!=connI+nbOfCells;)
6904     {
6905       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6906       if(std::find(types.begin(),types.end(),curType)!=types.end())
6907         {
6908           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6909         }
6910       types.push_back(curType);
6911       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6912       typeRangeVals.push_back((int)std::distance(connI,i));
6913     }
6914   //
6915   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6916   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6917   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6918   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6920   //
6921   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6922   code.resize(3*nbOfCastsFinal);
6923   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6924   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6925   for(int i=0;i<nbOfCastsFinal;i++)
6926     {
6927       int castId=castsPresent->getIJ(i,0);
6928       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6929       idsInPflPerType2.push_back(tmp3);
6930       code[3*i]=(int)types[castId];
6931       code[3*i+1]=tmp3->getNumberOfTuples();
6932       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6933       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6934         {
6935           tmp4->copyStringInfoFrom(*profile);
6936           idsPerType2.push_back(tmp4);
6937           code[3*i+2]=(int)idsPerType2.size()-1;
6938         }
6939       else
6940         {
6941           code[3*i+2]=-1;
6942         }
6943     }
6944   std::size_t sz2=idsInPflPerType2.size();
6945   idsInPflPerType.resize(sz2);
6946   for(std::size_t i=0;i<sz2;i++)
6947     {
6948       DataArrayInt *locDa=idsInPflPerType2[i];
6949       locDa->incrRef();
6950       idsInPflPerType[i]=locDa;
6951     }
6952   std::size_t sz=idsPerType2.size();
6953   idsPerType.resize(sz);
6954   for(std::size_t i=0;i<sz;i++)
6955     {
6956       DataArrayInt *locDa=idsPerType2[i];
6957       locDa->incrRef();
6958       idsPerType[i]=locDa;
6959     }
6960 }
6961
6962 /*!
6963  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6964  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6965  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6966  * 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.
6967  */
6968 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6969 {
6970   checkFullyDefined();
6971   nM1LevMesh->checkFullyDefined();
6972   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6973     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6974   if(_coords!=nM1LevMesh->getCoords())
6975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6976   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6978   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6979   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6980   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6981   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6982   tmp->setConnectivity(tmp0,tmp1);
6983   tmp->renumberCells(ret0->getConstPointer(),false);
6984   revDesc=tmp->getNodalConnectivity();
6985   revDescIndx=tmp->getNodalConnectivityIndex();
6986   DataArrayInt *ret=0;
6987   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6988     {
6989       int tmp2;
6990       ret->getMaxValue(tmp2);
6991       ret->decrRef();
6992       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6993       throw INTERP_KERNEL::Exception(oss.str().c_str());
6994     }
6995   nM1LevMeshIds=ret;
6996   //
6997   revDesc->incrRef();
6998   revDescIndx->incrRef();
6999   ret1->incrRef();
7000   ret0->incrRef();
7001   meshnM1Old2New=ret0;
7002   return ret1;
7003 }
7004
7005 /*!
7006  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7007  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7008  * in "Old to New" mode.
7009  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7010  *          this array using decrRef() as it is no more needed.
7011  *  \throw If the nodal connectivity of cells is not defined.
7012  */
7013 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7014 {
7015   checkConnectivityFullyDefined();
7016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7017   renumberCells(ret->getConstPointer(),false);
7018   return ret.retn();
7019 }
7020
7021 /*!
7022  * This methods checks that cells are sorted by their types.
7023  * This method makes asumption (no check) that connectivity is correctly set before calling.
7024  */
7025 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7026 {
7027   checkFullyDefined();
7028   const int *conn=_nodal_connec->getConstPointer();
7029   const int *connI=_nodal_connec_index->getConstPointer();
7030   int nbOfCells=getNumberOfCells();
7031   std::set<INTERP_KERNEL::NormalizedCellType> types;
7032   for(const int *i=connI;i!=connI+nbOfCells;)
7033     {
7034       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7035       if(types.find(curType)!=types.end())
7036         return false;
7037       types.insert(curType);
7038       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7039     }
7040   return true;
7041 }
7042
7043 /*!
7044  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7045  * The geometric type order is specified by MED file.
7046  * 
7047  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7048  */
7049 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7050 {
7051   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7052 }
7053
7054 /*!
7055  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7056  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7057  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7058  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7059  */
7060 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7061 {
7062   checkFullyDefined();
7063   const int *conn=_nodal_connec->getConstPointer();
7064   const int *connI=_nodal_connec_index->getConstPointer();
7065   int nbOfCells=getNumberOfCells();
7066   if(nbOfCells==0)
7067     return true;
7068   int lastPos=-1;
7069   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7070   for(const int *i=connI;i!=connI+nbOfCells;)
7071     {
7072       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7073       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7074       if(isTypeExists!=orderEnd)
7075         {
7076           int pos=(int)std::distance(orderBg,isTypeExists);
7077           if(pos<=lastPos)
7078             return false;
7079           lastPos=pos;
7080           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7081         }
7082       else
7083         {
7084           if(sg.find(curType)==sg.end())
7085             {
7086               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7087               sg.insert(curType);
7088             }
7089           else
7090             return false;
7091         }
7092     }
7093   return true;
7094 }
7095
7096 /*!
7097  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7098  * 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
7099  * 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'.
7100  */
7101 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7102 {
7103   checkConnectivityFullyDefined();
7104   int nbOfCells=getNumberOfCells();
7105   const int *conn=_nodal_connec->getConstPointer();
7106   const int *connI=_nodal_connec_index->getConstPointer();
7107   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7109   tmpa->alloc(nbOfCells,1);
7110   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7111   tmpb->fillWithZero();
7112   int *tmp=tmpa->getPointer();
7113   int *tmp2=tmpb->getPointer();
7114   for(const int *i=connI;i!=connI+nbOfCells;i++)
7115     {
7116       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7117       if(where!=orderEnd)
7118         {
7119           int pos=(int)std::distance(orderBg,where);
7120           tmp2[pos]++;
7121           tmp[std::distance(connI,i)]=pos;
7122         }
7123       else
7124         {
7125           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7126           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7127           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7128           throw INTERP_KERNEL::Exception(oss.str().c_str());
7129         }
7130     }
7131   nbPerType=tmpb.retn();
7132   return tmpa.retn();
7133 }
7134
7135 /*!
7136  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7137  *
7138  * \return a new object containing the old to new correspondance.
7139  *
7140  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7141  */
7142 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7143 {
7144   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7145 }
7146
7147 /*!
7148  * 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.
7149  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7150  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7151  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7152  */
7153 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7154 {
7155   DataArrayInt *nbPerType=0;
7156   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7157   nbPerType->decrRef();
7158   return tmpa->buildPermArrPerLevel();
7159 }
7160
7161 /*!
7162  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7163  * The number of cells remains unchanged after the call of this method.
7164  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7165  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7166  *
7167  * \return the array giving the correspondance old to new.
7168  */
7169 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7170 {
7171   checkFullyDefined();
7172   computeTypes();
7173   const int *conn=_nodal_connec->getConstPointer();
7174   const int *connI=_nodal_connec_index->getConstPointer();
7175   int nbOfCells=getNumberOfCells();
7176   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7177   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7178     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7179       {
7180         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7181         types.push_back(curType);
7182         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7183       }
7184   DataArrayInt *ret=DataArrayInt::New();
7185   ret->alloc(nbOfCells,1);
7186   int *retPtr=ret->getPointer();
7187   std::fill(retPtr,retPtr+nbOfCells,-1);
7188   int newCellId=0;
7189   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7190     {
7191       for(const int *i=connI;i!=connI+nbOfCells;i++)
7192         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7193           retPtr[std::distance(connI,i)]=newCellId++;
7194     }
7195   renumberCells(retPtr,false);
7196   return ret;
7197 }
7198
7199 /*!
7200  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7201  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7202  * This method makes asumption that connectivity is correctly set before calling.
7203  */
7204 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7205 {
7206   checkConnectivityFullyDefined();
7207   const int *conn=_nodal_connec->getConstPointer();
7208   const int *connI=_nodal_connec_index->getConstPointer();
7209   int nbOfCells=getNumberOfCells();
7210   std::vector<MEDCouplingUMesh *> ret;
7211   for(const int *i=connI;i!=connI+nbOfCells;)
7212     {
7213       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7214       int beginCellId=(int)std::distance(connI,i);
7215       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7216       int endCellId=(int)std::distance(connI,i);
7217       int sz=endCellId-beginCellId;
7218       int *cells=new int[sz];
7219       for(int j=0;j<sz;j++)
7220         cells[j]=beginCellId+j;
7221       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7222       delete [] cells;
7223       ret.push_back(m);
7224     }
7225   return ret;
7226 }
7227
7228 /*!
7229  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7230  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7231  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7232  *
7233  * \return a newly allocated instance, that the caller must manage.
7234  * \throw If \a this contains more than one geometric type.
7235  * \throw If the nodal connectivity of \a this is not fully defined.
7236  * \throw If the internal data is not coherent.
7237  */
7238 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7239 {
7240   checkConnectivityFullyDefined();
7241   if(_types.size()!=1)
7242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7243   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7244   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7245   ret->setCoords(getCoords());
7246   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7247   if(retC)
7248     {
7249       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7250       retC->setNodalConnectivity(c);
7251     }
7252   else
7253     {
7254       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7255       if(!retD)
7256         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7257       DataArrayInt *c=0,*ci=0;
7258       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7259       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7260       retD->setNodalConnectivity(cs,cis);
7261     }
7262   return ret.retn();
7263 }
7264
7265 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7266 {
7267   checkConnectivityFullyDefined();
7268   if(_types.size()!=1)
7269     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7270   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7271   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7272   if(cm.isDynamic())
7273     {
7274       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7275       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7276       throw INTERP_KERNEL::Exception(oss.str().c_str());
7277     }
7278   int nbCells=getNumberOfCells();
7279   int typi=(int)typ;
7280   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7282   int *outPtr=connOut->getPointer();
7283   const int *conn=_nodal_connec->begin();
7284   const int *connI=_nodal_connec_index->begin();
7285   nbNodesPerCell++;
7286   for(int i=0;i<nbCells;i++,connI++)
7287     {
7288       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7289         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7290       else
7291         {
7292           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 << ") !";
7293           throw INTERP_KERNEL::Exception(oss.str().c_str());
7294         }
7295     }
7296   return connOut.retn();
7297 }
7298
7299 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7300 {
7301   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7302   checkConnectivityFullyDefined();
7303   if(_types.size()!=1)
7304     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7305   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7306   if(lgth<nbCells)
7307     throw INTERP_KERNEL::Exception(msg0);
7308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7309   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7310   int *cp(c->getPointer()),*cip(ci->getPointer());
7311   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7312   cip[0]=0;
7313   for(int i=0;i<nbCells;i++,cip++,incip++)
7314     {
7315       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7316       int delta(stop-strt);
7317       if(delta>=1)
7318         {
7319           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7320             cp=std::copy(incp+strt,incp+stop,cp);
7321           else
7322             throw INTERP_KERNEL::Exception(msg0);
7323         }
7324       else
7325         throw INTERP_KERNEL::Exception(msg0);
7326       cip[1]=cip[0]+delta;
7327     }
7328   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7329 }
7330
7331 /*!
7332  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7333  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7334  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7335  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7336  * are not used here to avoid the build of big permutation array.
7337  *
7338  * \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
7339  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7340  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7341  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7342  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7343  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7344  * \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
7345  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7346  */
7347 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7348                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7349                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7350 {
7351   std::vector<const MEDCouplingUMesh *> ms2;
7352   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7353     if(*it)
7354       {
7355         (*it)->checkConnectivityFullyDefined();
7356         ms2.push_back(*it);
7357       }
7358   if(ms2.empty())
7359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7360   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7361   int meshDim=ms2[0]->getMeshDimension();
7362   std::vector<const MEDCouplingUMesh *> m1ssm;
7363   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7364   //
7365   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7366   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7367   int fake=0,rk=0;
7368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7369   ret1->alloc(0,1); ret2->alloc(0,1);
7370   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7371     {
7372       if(meshDim!=(*it)->getMeshDimension())
7373         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7374       if(refCoo!=(*it)->getCoords())
7375         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7376       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7377       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7378       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7379       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7380         {
7381           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7382           m1ssmSingleAuto.push_back(singleCell);
7383           m1ssmSingle.push_back(singleCell);
7384           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7385         }
7386     }
7387   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7389   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7390   for(std::size_t i=0;i<m1ssm.size();i++)
7391     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7393   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7394   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7395   return ret0.retn();
7396 }
7397
7398 /*!
7399  * This method returns a newly created DataArrayInt instance.
7400  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7401  */
7402 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7403 {
7404   checkFullyDefined();
7405   const int *conn=_nodal_connec->getConstPointer();
7406   const int *connIndex=_nodal_connec_index->getConstPointer();
7407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7408   for(const int *w=begin;w!=end;w++)
7409     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7410       ret->pushBackSilent(*w);
7411   return ret.retn();
7412 }
7413
7414 /*!
7415  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7416  * are in [0:getNumberOfCells())
7417  */
7418 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7419 {
7420   checkFullyDefined();
7421   const int *conn=_nodal_connec->getConstPointer();
7422   const int *connI=_nodal_connec_index->getConstPointer();
7423   int nbOfCells=getNumberOfCells();
7424   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7425   int *tmp=new int[nbOfCells];
7426   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7427     {
7428       int j=0;
7429       for(const int *i=connI;i!=connI+nbOfCells;i++)
7430         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7431           tmp[std::distance(connI,i)]=j++;
7432     }
7433   DataArrayInt *ret=DataArrayInt::New();
7434   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7435   ret->copyStringInfoFrom(*da);
7436   int *retPtr=ret->getPointer();
7437   const int *daPtr=da->getConstPointer();
7438   int nbOfElems=da->getNbOfElems();
7439   for(int k=0;k<nbOfElems;k++)
7440     retPtr[k]=tmp[daPtr[k]];
7441   delete [] tmp;
7442   return ret;
7443 }
7444
7445 /*!
7446  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7447  * This method \b works \b for mesh sorted by type.
7448  * cells whose ids is in 'idsPerGeoType' array.
7449  * This method conserves coords and name of mesh.
7450  */
7451 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7452 {
7453   std::vector<int> code=getDistributionOfTypes();
7454   std::size_t nOfTypesInThis=code.size()/3;
7455   int sz=0,szOfType=0;
7456   for(std::size_t i=0;i<nOfTypesInThis;i++)
7457     {
7458       if(code[3*i]!=type)
7459         sz+=code[3*i+1];
7460       else
7461         szOfType=code[3*i+1];
7462     }
7463   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7464     if(*work<0 || *work>=szOfType)
7465       {
7466         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7467         oss << ". It should be in [0," << szOfType << ") !";
7468         throw INTERP_KERNEL::Exception(oss.str().c_str());
7469       }
7470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7471   int *idsPtr=idsTokeep->getPointer();
7472   int offset=0;
7473   for(std::size_t i=0;i<nOfTypesInThis;i++)
7474     {
7475       if(code[3*i]!=type)
7476         for(int j=0;j<code[3*i+1];j++)
7477           *idsPtr++=offset+j;
7478       else
7479         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7480       offset+=code[3*i+1];
7481     }
7482   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7483   ret->copyTinyInfoFrom(this);
7484   return ret.retn();
7485 }
7486
7487 /*!
7488  * This method returns a vector of size 'this->getNumberOfCells()'.
7489  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7490  */
7491 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7492 {
7493   int ncell=getNumberOfCells();
7494   std::vector<bool> ret(ncell);
7495   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7496   const int *c=getNodalConnectivity()->getConstPointer();
7497   for(int i=0;i<ncell;i++)
7498     {
7499       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7500       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7501       ret[i]=cm.isQuadratic();
7502     }
7503   return ret;
7504 }
7505
7506 /*!
7507  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7508  */
7509 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7510 {
7511   if(other->getType()!=UNSTRUCTURED)
7512     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7513   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7514   return MergeUMeshes(this,otherC);
7515 }
7516
7517 /*!
7518  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7519  * computed by averaging coordinates of cell nodes, so this method is not a right
7520  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7521  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7522  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7523  *          components. The caller is to delete this array using decrRef() as it is
7524  *          no more needed.
7525  *  \throw If the coordinates array is not set.
7526  *  \throw If the nodal connectivity of cells is not defined.
7527  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7528  */
7529 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7530 {
7531   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7532   int spaceDim=getSpaceDimension();
7533   int nbOfCells=getNumberOfCells();
7534   ret->alloc(nbOfCells,spaceDim);
7535   ret->copyStringInfoFrom(*getCoords());
7536   double *ptToFill=ret->getPointer();
7537   const int *nodal=_nodal_connec->getConstPointer();
7538   const int *nodalI=_nodal_connec_index->getConstPointer();
7539   const double *coor=_coords->getConstPointer();
7540   for(int i=0;i<nbOfCells;i++)
7541     {
7542       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7543       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7544       ptToFill+=spaceDim;
7545     }
7546   return ret.retn();
7547 }
7548
7549 /*!
7550  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7551  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7552  * 
7553  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7554  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7555  * 
7556  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7557  * \throw If \a this is not fully defined (coordinates and connectivity)
7558  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7559  */
7560 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7561 {
7562   checkFullyDefined();
7563   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7564   int spaceDim=getSpaceDimension();
7565   int nbOfCells=getNumberOfCells();
7566   int nbOfNodes=getNumberOfNodes();
7567   ret->alloc(nbOfCells,spaceDim);
7568   double *ptToFill=ret->getPointer();
7569   const int *nodal=_nodal_connec->getConstPointer();
7570   const int *nodalI=_nodal_connec_index->getConstPointer();
7571   const double *coor=_coords->getConstPointer();
7572   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7573     {
7574       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7575       std::fill(ptToFill,ptToFill+spaceDim,0.);
7576       if(type!=INTERP_KERNEL::NORM_POLYHED)
7577         {
7578           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7579             {
7580               if(*conn>=0 && *conn<nbOfNodes)
7581                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7582               else
7583                 {
7584                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7585                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7586                 }
7587             }
7588           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7589           if(nbOfNodesInCell>0)
7590             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7591           else
7592             {
7593               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7594               throw INTERP_KERNEL::Exception(oss.str().c_str());
7595             }
7596         }
7597       else
7598         {
7599           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7600           s.erase(-1);
7601           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7602             {
7603               if(*it>=0 && *it<nbOfNodes)
7604                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7605               else
7606                 {
7607                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7608                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7609                 }
7610             }
7611           if(!s.empty())
7612             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7613           else
7614             {
7615               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7616               throw INTERP_KERNEL::Exception(oss.str().c_str());
7617             }
7618         }
7619     }
7620   return ret.retn();
7621 }
7622
7623 /*!
7624  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7625  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7626  * are specified via an array of cell ids. 
7627  *  \warning Validity of the specified cell ids is not checked! 
7628  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7629  *  \param [in] begin - an array of cell ids of interest.
7630  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7631  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7632  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7633  *          caller is to delete this array using decrRef() as it is no more needed. 
7634  *  \throw If the coordinates array is not set.
7635  *  \throw If the nodal connectivity of cells is not defined.
7636  *
7637  *  \if ENABLE_EXAMPLES
7638  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7639  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7640  *  \endif
7641  */
7642 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7643 {
7644   DataArrayDouble *ret=DataArrayDouble::New();
7645   int spaceDim=getSpaceDimension();
7646   int nbOfTuple=(int)std::distance(begin,end);
7647   ret->alloc(nbOfTuple,spaceDim);
7648   double *ptToFill=ret->getPointer();
7649   double *tmp=new double[spaceDim];
7650   const int *nodal=_nodal_connec->getConstPointer();
7651   const int *nodalI=_nodal_connec_index->getConstPointer();
7652   const double *coor=_coords->getConstPointer();
7653   for(const int *w=begin;w!=end;w++)
7654     {
7655       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7656       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7657       ptToFill+=spaceDim;
7658     }
7659   delete [] tmp;
7660   return ret;
7661 }
7662
7663 /*!
7664  * 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".
7665  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7666  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7667  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7668  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7669  * 
7670  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7671  * \throw If spaceDim!=3 or meshDim!=2.
7672  * \throw If connectivity of \a this is invalid.
7673  * \throw If connectivity of a cell in \a this points to an invalid node.
7674  */
7675 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7676 {
7677   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7678   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7679   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7680     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7681   ret->alloc(nbOfCells,4);
7682   double *retPtr(ret->getPointer());
7683   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7684   const double *coor(_coords->begin());
7685   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7686     {
7687       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7688       if(nodalI[1]-nodalI[0]>=3)
7689         {
7690           for(int j=0;j<3;j++)
7691             {
7692               int nodeId(nodal[nodalI[0]+1+j]);
7693               if(nodeId>=0 && nodeId<nbOfNodes)
7694                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7695               else
7696                 {
7697                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7698                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7699                 }
7700             }
7701         }
7702       else
7703         {
7704           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7705           throw INTERP_KERNEL::Exception(oss.str().c_str());
7706         }
7707       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7708       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7709     }
7710   return ret.retn();
7711 }
7712
7713 /*!
7714  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7715  * 
7716  */
7717 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7718 {
7719   if(!da)
7720     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7721   da->checkAllocated();
7722   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7723   ret->setCoords(da);
7724   int nbOfTuples=da->getNumberOfTuples();
7725   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7726   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7727   c->alloc(2*nbOfTuples,1);
7728   cI->alloc(nbOfTuples+1,1);
7729   int *cp=c->getPointer();
7730   int *cip=cI->getPointer();
7731   *cip++=0;
7732   for(int i=0;i<nbOfTuples;i++)
7733     {
7734       *cp++=INTERP_KERNEL::NORM_POINT1;
7735       *cp++=i;
7736       *cip++=2*(i+1);
7737     }
7738   ret->setConnectivity(c,cI,true);
7739   return ret.retn();
7740 }
7741 /*!
7742  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7743  * Cells and nodes of
7744  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7745  *  \param [in] mesh1 - the first mesh.
7746  *  \param [in] mesh2 - the second mesh.
7747  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7748  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7749  *          is no more needed.
7750  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7751  *  \throw If the coordinates array is not set in none of the meshes.
7752  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7753  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7754  */
7755 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7756 {
7757   std::vector<const MEDCouplingUMesh *> tmp(2);
7758   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7759   return MergeUMeshes(tmp);
7760 }
7761
7762 /*!
7763  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7764  * Cells and nodes of
7765  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7766  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7767  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7768  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7769  *          is no more needed.
7770  *  \throw If \a a.size() == 0.
7771  *  \throw If \a a[ *i* ] == NULL.
7772  *  \throw If the coordinates array is not set in none of the meshes.
7773  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7774  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7775  */
7776 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7777 {
7778   std::size_t sz=a.size();
7779   if(sz==0)
7780     return MergeUMeshesLL(a);
7781   for(std::size_t ii=0;ii<sz;ii++)
7782     if(!a[ii])
7783       {
7784         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7785         throw INTERP_KERNEL::Exception(oss.str().c_str());
7786       }
7787   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7788   std::vector< const MEDCouplingUMesh * > aa(sz);
7789   int spaceDim=-3;
7790   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7791     {
7792       const MEDCouplingUMesh *cur=a[i];
7793       const DataArrayDouble *coo=cur->getCoords();
7794       if(coo)
7795         spaceDim=coo->getNumberOfComponents();
7796     }
7797   if(spaceDim==-3)
7798     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7799   for(std::size_t i=0;i<sz;i++)
7800     {
7801       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7802       aa[i]=bb[i];
7803     }
7804   return MergeUMeshesLL(aa);
7805 }
7806
7807 /// @cond INTERNAL
7808
7809 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7810 {
7811   if(a.empty())
7812     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7813   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7814   int meshDim=(*it)->getMeshDimension();
7815   int nbOfCells=(*it)->getNumberOfCells();
7816   int meshLgth=(*it++)->getMeshLength();
7817   for(;it!=a.end();it++)
7818     {
7819       if(meshDim!=(*it)->getMeshDimension())
7820         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7821       nbOfCells+=(*it)->getNumberOfCells();
7822       meshLgth+=(*it)->getMeshLength();
7823     }
7824   std::vector<const MEDCouplingPointSet *> aps(a.size());
7825   std::copy(a.begin(),a.end(),aps.begin());
7826   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7827   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7828   ret->setCoords(pts);
7829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7830   c->alloc(meshLgth,1);
7831   int *cPtr=c->getPointer();
7832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7833   cI->alloc(nbOfCells+1,1);
7834   int *cIPtr=cI->getPointer();
7835   *cIPtr++=0;
7836   int offset=0;
7837   int offset2=0;
7838   for(it=a.begin();it!=a.end();it++)
7839     {
7840       int curNbOfCell=(*it)->getNumberOfCells();
7841       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7842       const int *curC=(*it)->_nodal_connec->getConstPointer();
7843       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7844       for(int j=0;j<curNbOfCell;j++)
7845         {
7846           const int *src=curC+curCI[j];
7847           *cPtr++=*src++;
7848           for(;src!=curC+curCI[j+1];src++,cPtr++)
7849             {
7850               if(*src!=-1)
7851                 *cPtr=*src+offset2;
7852               else
7853                 *cPtr=-1;
7854             }
7855         }
7856       offset+=curCI[curNbOfCell];
7857       offset2+=(*it)->getNumberOfNodes();
7858     }
7859   //
7860   ret->setConnectivity(c,cI,true);
7861   return ret.retn();
7862 }
7863
7864 /// @endcond
7865
7866 /*!
7867  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7868  * dimension and sharing the node coordinates array.
7869  * All cells of the first mesh precede all cells of the second mesh
7870  * within the result mesh. 
7871  *  \param [in] mesh1 - the first mesh.
7872  *  \param [in] mesh2 - the second mesh.
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 mesh1 == NULL or \a mesh2 == NULL.
7877  *  \throw If the meshes do not share the node coordinates array.
7878  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7879  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7880  */
7881 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7882 {
7883   std::vector<const MEDCouplingUMesh *> tmp(2);
7884   tmp[0]=mesh1; tmp[1]=mesh2;
7885   return MergeUMeshesOnSameCoords(tmp);
7886 }
7887
7888 /*!
7889  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7890  * dimension and sharing the node coordinates array.
7891  * All cells of the *i*-th mesh precede all cells of the
7892  * (*i*+1)-th mesh within the result mesh.
7893  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7894  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7895  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7896  *          is no more needed.
7897  *  \throw If \a a.size() == 0.
7898  *  \throw If \a a[ *i* ] == NULL.
7899  *  \throw If the meshes do not share the node coordinates array.
7900  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7901  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7902  */
7903 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7904 {
7905   if(meshes.empty())
7906     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7907   for(std::size_t ii=0;ii<meshes.size();ii++)
7908     if(!meshes[ii])
7909       {
7910         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7911         throw INTERP_KERNEL::Exception(oss.str().c_str());
7912       }
7913   const DataArrayDouble *coords=meshes.front()->getCoords();
7914   int meshDim=meshes.front()->getMeshDimension();
7915   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7916   int meshLgth=0;
7917   int meshIndexLgth=0;
7918   for(;iter!=meshes.end();iter++)
7919     {
7920       if(coords!=(*iter)->getCoords())
7921         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7922       if(meshDim!=(*iter)->getMeshDimension())
7923         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7924       meshLgth+=(*iter)->getMeshLength();
7925       meshIndexLgth+=(*iter)->getNumberOfCells();
7926     }
7927   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7928   nodal->alloc(meshLgth,1);
7929   int *nodalPtr=nodal->getPointer();
7930   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7931   nodalIndex->alloc(meshIndexLgth+1,1);
7932   int *nodalIndexPtr=nodalIndex->getPointer();
7933   int offset=0;
7934   for(iter=meshes.begin();iter!=meshes.end();iter++)
7935     {
7936       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7937       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7938       int nbOfCells=(*iter)->getNumberOfCells();
7939       int meshLgth2=(*iter)->getMeshLength();
7940       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7941       if(iter!=meshes.begin())
7942         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7943       else
7944         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7945       offset+=meshLgth2;
7946     }
7947   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7948   ret->setName("merge");
7949   ret->setMeshDimension(meshDim);
7950   ret->setConnectivity(nodal,nodalIndex,true);
7951   ret->setCoords(coords);
7952   return ret;
7953 }
7954
7955 /*!
7956  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7957  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7958  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7959  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7960  * New" mode are returned for each input mesh.
7961  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7962  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7963  *          valid values [0,1,2], see zipConnectivityTraducer().
7964  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7965  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7966  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7967  *          no more needed.
7968  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7969  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7970  *          is no more needed.
7971  *  \throw If \a meshes.size() == 0.
7972  *  \throw If \a meshes[ *i* ] == NULL.
7973  *  \throw If the meshes do not share the node coordinates array.
7974  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7975  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7976  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7977  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7978  */
7979 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7980 {
7981   //All checks are delegated to MergeUMeshesOnSameCoords
7982   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7984   corr.resize(meshes.size());
7985   std::size_t nbOfMeshes=meshes.size();
7986   int offset=0;
7987   const int *o2nPtr=o2n->getConstPointer();
7988   for(std::size_t i=0;i<nbOfMeshes;i++)
7989     {
7990       DataArrayInt *tmp=DataArrayInt::New();
7991       int curNbOfCells=meshes[i]->getNumberOfCells();
7992       tmp->alloc(curNbOfCells,1);
7993       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7994       offset+=curNbOfCells;
7995       tmp->setName(meshes[i]->getName());
7996       corr[i]=tmp;
7997     }
7998   return ret.retn();
7999 }
8000
8001 /*!
8002  * Makes all given meshes share the nodal connectivity array. The common connectivity
8003  * array is created by concatenating the connectivity arrays of all given meshes. All
8004  * the given meshes must be of the same space dimension but dimension of cells **can
8005  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8006  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8007  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8008  *  \param [in,out] meshes - a vector of meshes to update.
8009  *  \throw If any of \a meshes is NULL.
8010  *  \throw If the coordinates array is not set in any of \a meshes.
8011  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8012  *  \throw If \a meshes are of different space dimension.
8013  */
8014 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8015 {
8016   std::size_t sz=meshes.size();
8017   if(sz==0 || sz==1)
8018     return;
8019   std::vector< const DataArrayDouble * > coords(meshes.size());
8020   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8021   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8022     {
8023       if((*it))
8024         {
8025           (*it)->checkConnectivityFullyDefined();
8026           const DataArrayDouble *coo=(*it)->getCoords();
8027           if(coo)
8028             *it2=coo;
8029           else
8030             {
8031               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8032               oss << " has no coordinate array defined !";
8033               throw INTERP_KERNEL::Exception(oss.str().c_str());
8034             }
8035         }
8036       else
8037         {
8038           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8039           oss << " is null !";
8040           throw INTERP_KERNEL::Exception(oss.str().c_str());
8041         }
8042     }
8043   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8044   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8045   int offset=(*it)->getNumberOfNodes();
8046   (*it++)->setCoords(res);
8047   for(;it!=meshes.end();it++)
8048     {
8049       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8050       (*it)->setCoords(res);
8051       (*it)->shiftNodeNumbersInConn(offset);
8052       offset+=oldNumberOfNodes;
8053     }
8054 }
8055
8056 /*!
8057  * Merges nodes coincident with a given precision within all given meshes that share
8058  * the nodal connectivity array. The given meshes **can be of different** mesh
8059  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8060  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8061  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8062  *  \param [in,out] meshes - a vector of meshes to update.
8063  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8064  *  \throw If any of \a meshes is NULL.
8065  *  \throw If the \a meshes do not share the same node coordinates array.
8066  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8067  */
8068 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8069 {
8070   if(meshes.empty())
8071     return ;
8072   std::set<const DataArrayDouble *> s;
8073   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8074     {
8075       if(*it)
8076         s.insert((*it)->getCoords());
8077       else
8078         {
8079           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 !";
8080           throw INTERP_KERNEL::Exception(oss.str().c_str());
8081         }
8082     }
8083   if(s.size()!=1)
8084     {
8085       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 !";
8086       throw INTERP_KERNEL::Exception(oss.str().c_str());
8087     }
8088   const DataArrayDouble *coo=*(s.begin());
8089   if(!coo)
8090     return;
8091   //
8092   DataArrayInt *comm,*commI;
8093   coo->findCommonTuples(eps,-1,comm,commI);
8094   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8095   int oldNbOfNodes=coo->getNumberOfTuples();
8096   int newNbOfNodes;
8097   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8098   if(oldNbOfNodes==newNbOfNodes)
8099     return ;
8100   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8101   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8102     {
8103       (*it)->renumberNodesInConn(o2n->getConstPointer());
8104       (*it)->setCoords(newCoords);
8105     } 
8106 }
8107
8108 /*!
8109  * 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.
8110  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8111  * \param isQuad specifies the policy of connectivity.
8112  * @ret in/out parameter in which the result will be append
8113  */
8114 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8115 {
8116   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8117   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8118   ret.push_back(cm.getExtrudedType());
8119   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8120   switch(flatType)
8121   {
8122     case INTERP_KERNEL::NORM_POINT1:
8123       {
8124         ret.push_back(connBg[1]);
8125         ret.push_back(connBg[1]+nbOfNodesPerLev);
8126         break;
8127       }
8128     case INTERP_KERNEL::NORM_SEG2:
8129       {
8130         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8131         ret.insert(ret.end(),conn,conn+4);
8132         break;
8133       }
8134     case INTERP_KERNEL::NORM_SEG3:
8135       {
8136         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8137         ret.insert(ret.end(),conn,conn+8);
8138         break;
8139       }
8140     case INTERP_KERNEL::NORM_QUAD4:
8141       {
8142         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8143         ret.insert(ret.end(),conn,conn+8);
8144         break;
8145       }
8146     case INTERP_KERNEL::NORM_TRI3:
8147       {
8148         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8149         ret.insert(ret.end(),conn,conn+6);
8150         break;
8151       }
8152     case INTERP_KERNEL::NORM_TRI6:
8153       {
8154         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,
8155           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8156         ret.insert(ret.end(),conn,conn+15);
8157         break;
8158       }
8159     case INTERP_KERNEL::NORM_QUAD8:
8160       {
8161         int conn[20]={
8162           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8163           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8164           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8165         };
8166         ret.insert(ret.end(),conn,conn+20);
8167         break;
8168       }
8169     case INTERP_KERNEL::NORM_POLYGON:
8170       {
8171         std::back_insert_iterator< std::vector<int> > ii(ret);
8172         std::copy(connBg+1,connEnd,ii);
8173         *ii++=-1;
8174         std::reverse_iterator<const int *> rConnBg(connEnd);
8175         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8176         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8177         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8178         for(std::size_t i=0;i<nbOfRadFaces;i++)
8179           {
8180             *ii++=-1;
8181             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8182             std::copy(conn,conn+4,ii);
8183           }
8184         break;
8185       }
8186     default:
8187       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8188   }
8189 }
8190
8191 /*!
8192  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8193  */
8194 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8195 {
8196   std::size_t i, ip1;
8197   double v[3]={0.,0.,0.};
8198   std::size_t sz=std::distance(begin,end);
8199   if(isQuadratic)
8200     sz/=2;
8201   for(i=0;i<sz;i++)
8202     {
8203       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];
8204       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8205       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8206     }
8207   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8208
8209   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8210   // SEG3 forming a circle):
8211   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8212     {
8213       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8214       for(std::size_t j=0;j<sz;j++)
8215         {
8216           if (j%2)  // current point i is quadratic, next point i+1 is standard
8217             {
8218               i = sz+j;
8219               ip1 = (j+1)%sz; // ip1 = "i+1"
8220             }
8221           else      // current point i is standard, next point i+1 is quadratic
8222             {
8223               i = j;
8224               ip1 = j+sz;
8225             }
8226           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8227           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8228           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8229         }
8230       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8231     }
8232   return (ret>0.);
8233 }
8234
8235 /*!
8236  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8237  */
8238 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8239 {
8240   std::vector<std::pair<int,int> > edges;
8241   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8242   const int *bgFace=begin;
8243   for(std::size_t i=0;i<nbOfFaces;i++)
8244     {
8245       const int *endFace=std::find(bgFace+1,end,-1);
8246       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8247       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8248         {
8249           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8250           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8251             return false;
8252           edges.push_back(p1);
8253         }
8254       bgFace=endFace+1;
8255     }
8256   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8257 }
8258
8259 /*!
8260  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8261  */
8262 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8263 {
8264   double vec0[3],vec1[3];
8265   std::size_t sz=std::distance(begin,end);
8266   if(sz%2!=0)
8267     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8268   int nbOfNodes=(int)sz/2;
8269   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8270   const double *pt0=coords+3*begin[0];
8271   const double *pt1=coords+3*begin[nbOfNodes];
8272   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8273   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8274 }
8275
8276 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8277 {
8278   std::size_t sz=std::distance(begin,end);
8279   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8280   std::size_t nbOfNodes(sz/2);
8281   std::copy(begin,end,(int *)tmp);
8282   for(std::size_t j=1;j<nbOfNodes;j++)
8283     {
8284       begin[j]=tmp[nbOfNodes-j];
8285       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8286     }
8287 }
8288
8289 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8290 {
8291   std::size_t sz=std::distance(begin,end);
8292   if(sz!=4)
8293     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8294   double vec0[3],vec1[3];
8295   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8296   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]; 
8297   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;
8298 }
8299
8300 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8301 {
8302   std::size_t sz=std::distance(begin,end);
8303   if(sz!=5)
8304     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8305   double vec0[3];
8306   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8307   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8308   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8309 }
8310
8311 /*!
8312  * 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 ) 
8313  * 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
8314  * a 2D space.
8315  *
8316  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8317  * \param [in] coords the coordinates with nb of components exactly equal to 3
8318  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8319  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8320  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8321  */
8322 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8323 {
8324   int nbFaces=std::count(begin+1,end,-1)+1;
8325   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8326   double *vPtr=v->getPointer();
8327   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8328   double *pPtr=p->getPointer();
8329   const int *stFaceConn=begin+1;
8330   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8331     {
8332       const int *endFaceConn=std::find(stFaceConn,end,-1);
8333       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8334       stFaceConn=endFaceConn+1;
8335     }
8336   pPtr=p->getPointer(); vPtr=v->getPointer();
8337   DataArrayInt *comm1=0,*commI1=0;
8338   v->findCommonTuples(eps,-1,comm1,commI1);
8339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8340   const int *comm1Ptr=comm1->getConstPointer();
8341   const int *commI1Ptr=commI1->getConstPointer();
8342   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8343   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8344   //
8345   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8346   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8347   mm->finishInsertingCells();
8348   //
8349   for(int i=0;i<nbOfGrps1;i++)
8350     {
8351       int vecId=comm1Ptr[commI1Ptr[i]];
8352       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8353       DataArrayInt *comm2=0,*commI2=0;
8354       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8355       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8356       const int *comm2Ptr=comm2->getConstPointer();
8357       const int *commI2Ptr=commI2->getConstPointer();
8358       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8359       for(int j=0;j<nbOfGrps2;j++)
8360         {
8361           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8362             {
8363               res->insertAtTheEnd(begin,end);
8364               res->pushBackSilent(-1);
8365             }
8366           else
8367             {
8368               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8369               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8370               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8371               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8372               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8373               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8374               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8375               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8376               const int *idsNodePtr=idsNode->getConstPointer();
8377               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];
8378               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8379               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8380               if(std::abs(norm)>eps)
8381                 {
8382                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8383                   mm3->rotate(center,vec,angle);
8384                 }
8385               mm3->changeSpaceDimension(2);
8386               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8387               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8388               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8389               int nbOfCells=mm4->getNumberOfCells();
8390               for(int k=0;k<nbOfCells;k++)
8391                 {
8392                   int l=0;
8393                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8394                     res->pushBackSilent(idsNodePtr[*work]);
8395                   res->pushBackSilent(-1);
8396                 }
8397             }
8398         }
8399     }
8400   res->popBackSilent();
8401 }
8402
8403 /*!
8404  * 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
8405  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8406  * 
8407  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8408  * \param [in] coords coordinates expected to have 3 components.
8409  * \param [in] begin start of the nodal connectivity of the face.
8410  * \param [in] end end of the nodal connectivity (excluded) of the face.
8411  * \param [out] v the normalized vector of size 3
8412  * \param [out] p the pos of plane
8413  */
8414 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8415 {
8416   std::size_t nbPoints=std::distance(begin,end);
8417   if(nbPoints<3)
8418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8419   double vec[3]={0.,0.,0.};
8420   std::size_t j=0;
8421   bool refFound=false;
8422   for(;j<nbPoints-1 && !refFound;j++)
8423     {
8424       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8425       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8426       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8427       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8428       if(norm>eps)
8429         {
8430           refFound=true;
8431           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8432         }
8433     }
8434   for(std::size_t i=j;i<nbPoints-1;i++)
8435     {
8436       double curVec[3];
8437       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8438       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8439       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8440       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8441       if(norm<eps)
8442         continue;
8443       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8444       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];
8445       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8446       if(norm>eps)
8447         {
8448           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8449           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8450           return ;
8451         }
8452     }
8453   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8454 }
8455
8456 /*!
8457  * This method tries to obtain a well oriented polyhedron.
8458  * If the algorithm fails, an exception will be thrown.
8459  */
8460 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8461 {
8462   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8463   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8464   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8465   isPerm[0]=true;
8466   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8467   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8468   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8469   //
8470   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8471     {
8472       bgFace=begin;
8473       std::size_t smthChanged=0;
8474       for(std::size_t i=0;i<nbOfFaces;i++)
8475         {
8476           endFace=std::find(bgFace+1,end,-1);
8477           nbOfEdgesInFace=std::distance(bgFace,endFace);
8478           if(!isPerm[i])
8479             {
8480               bool b;
8481               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8482                 {
8483                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8484                   std::pair<int,int> p2(p1.second,p1.first);
8485                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8486                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8487                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8488                 }
8489               if(isPerm[i])
8490                 { 
8491                   if(!b)
8492                     std::reverse(bgFace+1,endFace);
8493                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8494                     {
8495                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8496                       std::pair<int,int> p2(p1.second,p1.first);
8497                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8498                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8499                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8500                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8501                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8502                       if(it!=edgesOK.end())
8503                         {
8504                           edgesOK.erase(it);
8505                           edgesFinished.push_back(p1);
8506                         }
8507                       else
8508                         edgesOK.push_back(p1);
8509                     }
8510                 }
8511             }
8512           bgFace=endFace+1;
8513         }
8514       if(smthChanged==0)
8515         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8516     }
8517   if(!edgesOK.empty())
8518     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8519   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8520     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8521       bgFace=begin;
8522       for(std::size_t i=0;i<nbOfFaces;i++)
8523         {
8524           endFace=std::find(bgFace+1,end,-1);
8525           std::reverse(bgFace+1,endFace);
8526           bgFace=endFace+1;
8527         }
8528     }
8529 }
8530
8531 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8532 {
8533   int nbOfNodesExpected(skin->getNumberOfNodes());
8534   const int *n2oPtr(n2o->getConstPointer());
8535   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8536   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8537   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8538   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8539   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8541   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8542   if(nbOfNodesExpected<1)
8543     return ret.retn();
8544   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8545   *work++=n2oPtr[prevNode];
8546   for(int i=1;i<nbOfNodesExpected;i++)
8547     {
8548       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8549         {
8550           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8551           conn.erase(prevNode);
8552           if(conn.size()==1)
8553             {
8554               int curNode(*(conn.begin()));
8555               *work++=n2oPtr[curNode];
8556               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8557               shar.erase(prevCell);
8558               if(shar.size()==1)
8559                 {
8560                   prevCell=*(shar.begin());
8561                   prevNode=curNode;
8562                 }
8563               else
8564                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8565             }
8566           else
8567             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8568         }
8569       else
8570         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8571     }
8572   return ret.retn();
8573 }
8574
8575 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8576 {
8577   int nbOfNodesExpected(skin->getNumberOfNodes());
8578   int nbOfTurn(nbOfNodesExpected/2);
8579   const int *n2oPtr(n2o->getConstPointer());
8580   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8581   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8582   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8583   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8584   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8585   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8586   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8587   if(nbOfNodesExpected<1)
8588     return ret.retn();
8589   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8590   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8591   for(int i=1;i<nbOfTurn;i++)
8592     {
8593       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8594         {
8595           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8596           conn.erase(prevNode);
8597           if(conn.size()==1)
8598             {
8599               int curNode(*(conn.begin()));
8600               *work=n2oPtr[curNode];
8601               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8602               shar.erase(prevCell);
8603               if(shar.size()==1)
8604                 {
8605                   int curCell(*(shar.begin()));
8606                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8607                   prevCell=curCell;
8608                   prevNode=curNode;
8609                   work++;
8610                 }
8611               else
8612                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8613             }
8614           else
8615             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8616         }
8617       else
8618         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8619     }
8620   return ret.retn();
8621 }
8622
8623 /*!
8624  * This method makes the assumption spacedimension == meshdimension == 2.
8625  * This method works only for linear cells.
8626  * 
8627  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8628  */
8629 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8630 {
8631   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8632     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8633   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8634   int oldNbOfNodes(skin->getNumberOfNodes());
8635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8636   int nbOfNodesExpected(skin->getNumberOfNodes());
8637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8638   int nbCells(skin->getNumberOfCells());
8639   if(nbCells==nbOfNodesExpected)
8640     return buildUnionOf2DMeshLinear(skin,n2o);
8641   else if(2*nbCells==nbOfNodesExpected)
8642     return buildUnionOf2DMeshQuadratic(skin,n2o);
8643   else
8644     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8645 }
8646
8647 /*!
8648  * This method makes the assumption spacedimension == meshdimension == 3.
8649  * This method works only for linear cells.
8650  * 
8651  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8652  */
8653 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8654 {
8655   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8656     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8657   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8658   const int *conn=m->getNodalConnectivity()->getConstPointer();
8659   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8660   int nbOfCells=m->getNumberOfCells();
8661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8662   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8663   if(nbOfCells<1)
8664     return ret.retn();
8665   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8666   for(int i=1;i<nbOfCells;i++)
8667     {
8668       *work++=-1;
8669       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8670     }
8671   return ret.retn();
8672 }
8673
8674 /*!
8675  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8676  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8677  */
8678 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8679 {
8680   double *w=zipFrmt;
8681   if(spaceDim==3)
8682     for(int i=0;i<nbOfNodesInCell;i++)
8683       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8684   else if(spaceDim==2)
8685     {
8686       for(int i=0;i<nbOfNodesInCell;i++)
8687         {
8688           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8689           *w++=0.;
8690         }
8691     }
8692   else
8693     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8694 }
8695
8696 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8697 {
8698   int nbOfCells=getNumberOfCells();
8699   if(nbOfCells<=0)
8700     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8701   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};
8702   ofs << "  <" << getVTKDataSetType() << ">\n";
8703   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8704   ofs << "      <PointData>\n" << pointData << std::endl;
8705   ofs << "      </PointData>\n";
8706   ofs << "      <CellData>\n" << cellData << std::endl;
8707   ofs << "      </CellData>\n";
8708   ofs << "      <Points>\n";
8709   if(getSpaceDimension()==3)
8710     _coords->writeVTK(ofs,8,"Points",byteData);
8711   else
8712     {
8713       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8714       coo->writeVTK(ofs,8,"Points",byteData);
8715     }
8716   ofs << "      </Points>\n";
8717   ofs << "      <Cells>\n";
8718   const int *cPtr=_nodal_connec->getConstPointer();
8719   const int *cIPtr=_nodal_connec_index->getConstPointer();
8720   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8722   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8723   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8724   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8725   int szFaceOffsets=0,szConn=0;
8726   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8727     {
8728       *w2=cPtr[cIPtr[i]];
8729       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8730         {
8731           *w1=-1;
8732           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8733           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8734         }
8735       else
8736         {
8737           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8738           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8739           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8740           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8741           w4=std::copy(c.begin(),c.end(),w4);
8742         }
8743     }
8744   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8745   types->writeVTK(ofs,8,"UInt8","types",byteData);
8746   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8747   if(szFaceOffsets!=0)
8748     {//presence of Polyhedra
8749       connectivity->reAlloc(szConn);
8750       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8751       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8752       w1=faces->getPointer();
8753       for(int i=0;i<nbOfCells;i++)
8754         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8755           {
8756             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8757             *w1++=nbFaces;
8758             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8759             for(int j=0;j<nbFaces;j++)
8760               {
8761                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8762                 *w1++=(int)std::distance(w6,w5);
8763                 w1=std::copy(w6,w5,w1);
8764                 w6=w5+1;
8765               }
8766           }
8767       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8768     }
8769   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8770   ofs << "      </Cells>\n";
8771   ofs << "    </Piece>\n";
8772   ofs << "  </" << getVTKDataSetType() << ">\n";
8773 }
8774
8775 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8776 {
8777   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8778   if(_mesh_dim==-2)
8779     { stream << " Not set !"; return ; }
8780   stream << " Mesh dimension : " << _mesh_dim << ".";
8781   if(_mesh_dim==-1)
8782     return ;
8783   if(!_coords)
8784     { stream << " No coordinates set !"; return ; }
8785   if(!_coords->isAllocated())
8786     { stream << " Coordinates set but not allocated !"; return ; }
8787   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8788   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8789   if(!_nodal_connec_index)
8790     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8791   if(!_nodal_connec_index->isAllocated())
8792     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8793   int lgth=_nodal_connec_index->getNumberOfTuples();
8794   int cpt=_nodal_connec_index->getNumberOfComponents();
8795   if(cpt!=1 || lgth<1)
8796     return ;
8797   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8798 }
8799
8800 std::string MEDCouplingUMesh::getVTKDataSetType() const
8801 {
8802   return std::string("UnstructuredGrid");
8803 }
8804
8805 std::string MEDCouplingUMesh::getVTKFileExtension() const
8806 {
8807   return std::string("vtu");
8808 }
8809
8810 /*!
8811  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8812  * returns a result mesh constituted by polygons.
8813  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8814  * all nodes from m2.
8815  * The meshes should be in 2D space. In
8816  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8817  * meshes.
8818  *  \param [in] m1 - the first input mesh which is a partitioned object. The mesh must be so that each point in the space covered by \a m1
8819  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8820  *  \param [in] m2 - the second input mesh which is a partition tool. The mesh must be so that each point in the space covered by \a m2
8821  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8822  *  \param [in] eps - precision used to detect coincident mesh entities.
8823  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8824  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8825  *         this array using decrRef() as it is no more needed.
8826  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8827  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8828  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8829  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8830  *         it is no more needed.  
8831  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8832  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8833  *         is no more needed.  
8834  *  \throw If the coordinates array is not set in any of the meshes.
8835  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8836  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8837  *
8838  *  \sa conformize2D, mergeNodes
8839  */
8840 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8841                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8842 {
8843   if(!m1 || !m2)
8844     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8845   m1->checkFullyDefined();
8846   m2->checkFullyDefined();
8847   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8848     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8849
8850   // Step 1: compute all edge intersections (new nodes)
8851   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8852   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8853   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8854   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8855   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8856                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8857                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8858   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8859   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8860   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8861
8862   // Step 2: re-order newly created nodes according to the ordering found in m2
8863   std::vector< std::vector<int> > intersectEdge2;
8864   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8865   subDiv2.clear(); dd5=0; dd6=0;
8866
8867   // Step 3:
8868   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8869   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8870   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8871                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8872
8873   // Step 4: Prepare final result:
8874   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8875   addCooDa->alloc((int)(addCoo.size())/2,2);
8876   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8877   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8878   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8879   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8880   std::vector<const DataArrayDouble *> coordss(4);
8881   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8882   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8883   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8885   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8888   ret->setConnectivity(conn,connI,true);
8889   ret->setCoords(coo);
8890   cellNb1=c1.retn(); cellNb2=c2.retn();
8891   return ret.retn();
8892 }
8893
8894 /// @cond INTERNAL
8895
8896 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8897 {
8898   if(candidates.empty())
8899     return false;
8900   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8901     {
8902       const std::vector<int>& pool(intersectEdge1[*it]);
8903       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8904       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8905         {
8906           retVal=*it+1;
8907           return true;
8908         }
8909       tmp[0]=stop; tmp[1]=start;
8910       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8911         {
8912           retVal=-*it-1;
8913           return true;
8914         }
8915     }
8916   return false;
8917 }
8918
8919 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,
8920                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8921 {
8922   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8923   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8924   int nCells(mesh1D->getNumberOfCells());
8925   if(nCells!=(int)intersectEdge2.size())
8926     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8927   const DataArrayDouble *coo2(mesh1D->getCoords());
8928   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8929   const double *coo2Ptr(coo2->begin());
8930   int offset1(coords1->getNumberOfTuples());
8931   int offset2(offset1+coo2->getNumberOfTuples());
8932   int offset3(offset2+addCoo.size()/2);
8933   std::vector<double> addCooQuad;
8934   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8935   int tmp[4],cicnt(0),kk(0);
8936   for(int i=0;i<nCells;i++)
8937     {
8938       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8939       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8940       const std::vector<int>& subEdges(intersectEdge2[i]);
8941       int nbSubEdge(subEdges.size()/2);
8942       for(int j=0;j<nbSubEdge;j++,kk++)
8943         {
8944           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));
8945           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8946           INTERP_KERNEL::Edge *e2Ptr(e2);
8947           std::map<int,int>::const_iterator itm;
8948           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8949             {
8950               tmp[0]=INTERP_KERNEL::NORM_SEG3;
8951               itm=mergedNodes.find(subEdges[2*j]);
8952               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8953               itm=mergedNodes.find(subEdges[2*j+1]);
8954               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8955               tmp[3]=offset3+(int)addCooQuad.size()/2;
8956               double tmp2[2];
8957               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8958               cicnt+=4;
8959               cOut->insertAtTheEnd(tmp,tmp+4);
8960               ciOut->pushBackSilent(cicnt);
8961             }
8962           else
8963             {
8964               tmp[0]=INTERP_KERNEL::NORM_SEG2;
8965               itm=mergedNodes.find(subEdges[2*j]);
8966               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8967               itm=mergedNodes.find(subEdges[2*j+1]);
8968               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8969               cicnt+=3;
8970               cOut->insertAtTheEnd(tmp,tmp+3);
8971               ciOut->pushBackSilent(cicnt);
8972             }
8973           int tmp00;
8974           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8975             {
8976               idsInRetColinear->pushBackSilent(kk);
8977               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8978             }
8979         }
8980       e->decrRef();
8981     }
8982   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8983   ret->setConnectivity(cOut,ciOut,true);
8984   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8985   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8986   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8987   std::vector<const DataArrayDouble *> coordss(4);
8988   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8989   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8990   ret->setCoords(arr);
8991   return ret.retn();
8992 }
8993
8994 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8995 {
8996   std::vector<int> allEdges;
8997   for(const int *it2(descBg);it2!=descEnd;it2++)
8998     {
8999       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9000       if(*it2>0)
9001         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9002       else
9003         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9004     }
9005   std::size_t nb(allEdges.size());
9006   if(nb%2!=0)
9007     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9008   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9009   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9010   ret->setCoords(coords);
9011   ret->allocateCells(1);
9012   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9013   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9014     connOut[kk]=allEdges[2*kk];
9015   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9016   return ret.retn();
9017 }
9018
9019 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9020 {
9021   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9022   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9023   std::size_t ii(0);
9024   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9025   if(sz!=std::distance(descBg,descEnd))
9026     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9027   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9028   std::vector<int> allEdges,centers;
9029   const double *coordsPtr(coords->begin());
9030   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9031   int offset(coords->getNumberOfTuples());
9032   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9033     {
9034       INTERP_KERNEL::NormalizedCellType typeOfSon;
9035       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9036       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9037       if(*it2>0)
9038         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9039       else
9040         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9041       if(edge1.size()==2)
9042         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9043       else
9044         {//the current edge has been subsplit -> create corresponding centers.
9045           std::size_t nbOfCentersToAppend(edge1.size()/2);
9046           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9047           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9048           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9049           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9050             {
9051               double tmpp[2];
9052               const double *aa(coordsPtr+2*(*it3++));
9053               const double *bb(coordsPtr+2*(*it3++));
9054               ee->getMiddleOfPoints(aa,bb,tmpp);
9055               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9056               centers.push_back(offset+k);
9057             }
9058         }
9059     }
9060   std::size_t nb(allEdges.size());
9061   if(nb%2!=0)
9062     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9063   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9064   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9065   if(addCoo->empty())
9066     ret->setCoords(coords);
9067   else
9068     {
9069       addCoo->rearrange(2);
9070       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9071       ret->setCoords(addCoo);
9072     }
9073   ret->allocateCells(1);
9074   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9075   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9076     connOut[kk]=allEdges[2*kk];
9077   connOut.insert(connOut.end(),centers.begin(),centers.end());
9078   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9079   return ret.retn();
9080 }
9081
9082 /*!
9083  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9084  * of those edges.
9085  *
9086  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9087  */
9088 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9089 {
9090   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9091   if(!cm.isQuadratic())
9092     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9093   else
9094     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9095 }
9096
9097 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9098 {
9099   bool isQuad(false);
9100   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9101     {
9102       const INTERP_KERNEL::Edge *ee(*it);
9103       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9104         isQuad=true;
9105     }
9106   if(!isQuad)
9107     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9108   else
9109     {
9110       const double *coo(mesh2D->getCoords()->begin());
9111       std::size_t sz(conn.size());
9112       std::vector<double> addCoo;
9113       std::vector<int> conn2(conn);
9114       int offset(mesh2D->getNumberOfNodes());
9115       for(std::size_t i=0;i<sz;i++)
9116         {
9117           double tmp[2];
9118           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9119           addCoo.insert(addCoo.end(),tmp,tmp+2);
9120           conn2.push_back(offset+(int)i);
9121         }
9122       mesh2D->getCoords()->rearrange(1);
9123       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9124       mesh2D->getCoords()->rearrange(2);
9125       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9126     }
9127 }
9128
9129 /*!
9130  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9131  *
9132  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9133  * a set of edges defined in \a splitMesh1D.
9134  */
9135 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9136                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9137 {
9138   std::size_t nb(edge1Bis.size()/2);
9139   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9140   int iEnd(splitMesh1D->getNumberOfCells());
9141   if(iEnd==0)
9142     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9143   std::size_t ii,jj;
9144   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9145   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9146   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9147   //
9148   if(jj==nb)
9149     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9150       out0.resize(1); out1.resize(1);
9151       std::vector<int>& connOut(out0[0]);
9152       connOut.resize(nbOfEdgesOf2DCellSplit);
9153       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9154       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9155       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9156         {
9157           connOut[kk]=edge1Bis[2*kk];
9158           edgesPtr[kk]=edge1BisPtr[2*kk];
9159         }
9160     }
9161   else
9162     {
9163       // [i,iEnd[ contains the
9164       out0.resize(2); out1.resize(2);
9165       std::vector<int>& connOutLeft(out0[0]);
9166       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9167       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9168       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9169       for(std::size_t k=ii;k<jj+1;k++)
9170         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9171       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9172       for(int ik=0;ik<iEnd;ik++)
9173         {
9174           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9175           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9176           ees[ik]=ee;
9177         }
9178       for(int ik=iEnd-1;ik>=0;ik--)
9179         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9180       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9181         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9182       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9183       for(int ik=0;ik<iEnd;ik++)
9184         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9185       eright.insert(eright.end(),ees.begin(),ees.end());
9186     }
9187 }
9188
9189 /// @endcond
9190
9191 /// @cond INTERNAL
9192
9193 struct CellInfo
9194 {
9195 public:
9196   CellInfo() { }
9197   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9198 public:
9199   std::vector<int> _edges;
9200   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9201 };
9202
9203 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9204 {
9205   std::size_t nbe(edges.size());
9206   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9207   for(std::size_t i=0;i<nbe;i++)
9208     {
9209       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9210       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9211     }
9212   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9213   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9214   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9215 }
9216
9217 class EdgeInfo
9218 {
9219 public:
9220   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9221   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9222   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9223   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9224   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9225 private:
9226   int _istart;
9227   int _iend;
9228   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9229   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9230   int _left;
9231   int _right;
9232 };
9233
9234 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9235 {
9236   const MEDCouplingUMesh *mesh(_mesh);
9237   if(mesh)
9238     return ;
9239   if(_right<pos)
9240     return ;
9241   if(_left>pos)
9242     { _left++; _right++; return ; }
9243   if(_right==pos)
9244     {
9245       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9246       if((isLeft && isRight) || (!isLeft && !isRight))
9247         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9248       if(isLeft)
9249         return ;
9250       if(isRight)
9251         {
9252           _right++;
9253           return ;
9254         }
9255     }
9256   if(_left==pos)
9257     {
9258       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9259       if((isLeft && isRight) || (!isLeft && !isRight))
9260         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9261       if(isLeft)
9262         {
9263           _right++;
9264           return ;
9265         }
9266       if(isRight)
9267         {
9268           _left++;
9269           _right++;
9270           return ;
9271         }
9272     }
9273 }
9274
9275 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9276 {
9277   const MEDCouplingUMesh *mesh(_mesh);
9278   if(!mesh)
9279     {
9280       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9281     }
9282   else
9283     {// not fully splitting cell case
9284       if(mesh2D->getNumberOfCells()==1)
9285         {//little optimization. 1 cell no need to find in which cell mesh is !
9286           neighbors[0]=offset; neighbors[1]=offset;
9287           return;
9288         }
9289       else
9290         {
9291           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9292           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9293           if(cellId==-1)
9294             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9295           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9296         }
9297     }
9298 }
9299
9300 class VectorOfCellInfo
9301 {
9302 public:
9303   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9304   std::size_t size() const { return _pool.size(); }
9305   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9306   void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9307   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9308   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9309   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9310   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9311 private:
9312   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9313   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9314   const CellInfo& get(int pos) const;
9315   CellInfo& get(int pos);
9316 private:
9317   std::vector<CellInfo> _pool;
9318   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9319   std::vector<EdgeInfo> _edge_info;
9320 };
9321
9322 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9323 {
9324   _pool[0]._edges=edges;
9325   _pool[0]._edges_ptr=edgesPtr;
9326 }
9327
9328 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9329 {
9330   if(_pool.empty())
9331     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9332   if(_pool.size()==1)
9333     return 0;
9334   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9335   if(!zeMesh)
9336     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9337   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9338   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9339 }
9340
9341 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9342 {
9343   get(pos);//to check pos
9344   bool isFast(pos==0 && _pool.size()==1);
9345   std::size_t sz(edges.size());
9346   // dealing with edges
9347   if(sz==1)
9348     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9349   else
9350     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9351   //
9352   std::vector<CellInfo> pool(_pool.size()-1+sz);
9353   for(int i=0;i<pos;i++)
9354     pool[i]=_pool[i];
9355   for(std::size_t j=0;j<sz;j++)
9356     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9357   for(int i=pos+1;i<(int)_pool.size();i++)
9358     pool[i+sz-1]=_pool[i];
9359   _pool=pool;
9360   //
9361   if(sz==2)
9362     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9363   //
9364   if(isFast)
9365     {
9366       _ze_mesh=mesh;
9367       return ;
9368     }
9369   //
9370   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9371   if(pos>0)
9372     {
9373       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9374       ms.push_back(elt);
9375     }
9376   ms.push_back(mesh);
9377   if(pos<_ze_mesh->getNumberOfCells()-1)
9378   {
9379     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9380     ms.push_back(elt);
9381   }
9382   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9383   for(std::size_t j=0;j<ms2.size();j++)
9384     ms2[j]=ms[j];
9385   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9386 }
9387
9388 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9389 {
9390   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9391 }
9392
9393 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9394 {
9395   if(pos<0)
9396     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9397   int ret(0);
9398   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9399     {
9400       if((*it).isInMyRange(pos))
9401         return ret;
9402     }
9403   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9404 }
9405
9406 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9407 {
9408   get(pos);//to check;
9409   if(_edge_info.empty())
9410     return ;
9411   std::size_t sz(_edge_info.size()-1);
9412   for(std::size_t i=0;i<sz;i++)
9413     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9414 }
9415
9416 const CellInfo& VectorOfCellInfo::get(int pos) const
9417 {
9418   if(pos<0 || pos>=(int)_pool.size())
9419     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9420   return _pool[pos];
9421 }
9422
9423 CellInfo& VectorOfCellInfo::get(int pos)
9424 {
9425   if(pos<0 || pos>=(int)_pool.size())
9426     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9427   return _pool[pos];
9428 }
9429
9430 /*!
9431  * Given :
9432  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9433  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9434  *
9435  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9436  *
9437  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9438  *
9439  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9440  */
9441 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9442                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9443 {
9444   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9445   if(nbCellsInSplitMesh1D==0)
9446     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9447   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9448   std::size_t nb(allEdges.size()),jj;
9449   if(nb%2!=0)
9450     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9451   std::vector<int> edge1Bis(nb*2);
9452   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9453   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9454   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9455   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9456   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9457   //
9458   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9459   int *idsLeftRightPtr(idsLeftRight->getPointer());
9460   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9461   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9462     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9463       int iEnd(iStart);
9464       for(;iEnd<nbCellsInSplitMesh1D;)
9465         {
9466           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9467           if(jj!=nb)
9468             break;
9469           else
9470             iEnd++;
9471         }
9472       if(iEnd<nbCellsInSplitMesh1D)
9473         iEnd++;
9474       //
9475       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9476       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9477       //
9478       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9479       retTmp->setCoords(splitMesh1D->getCoords());
9480       retTmp->allocateCells();
9481
9482       std::vector< std::vector<int> > out0;
9483       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9484
9485       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9486       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9487         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9488       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9489       //
9490       iStart=iEnd;
9491     }
9492   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9493     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9494   return pool.getZeMesh().retn();
9495 }
9496
9497 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9498                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9499                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9500 {
9501   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9502   //
9503   std::vector<int> allEdges;
9504   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9505   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9506     {
9507       int edgeId(std::abs(*it)-1);
9508       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9509       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9510       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9511       if(*it>0)
9512         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9513       else
9514         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9515       std::size_t sz(edge1.size());
9516       for(std::size_t cnt=0;cnt<sz;cnt++)
9517         allEdgesPtr.push_back(ee);
9518     }
9519   //
9520   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9521 }
9522
9523 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9524 {
9525   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9526     {//easy case comparison not
9527       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9528     }
9529   else if(typ1.isQuadratic() && typ2.isQuadratic())
9530     {
9531       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9532       if(!status0)
9533         return false;
9534       if(conn1[2]==conn2[2])
9535         return true;
9536       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9537       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9538       return dist<eps;
9539     }
9540   else
9541     {//only one is quadratic
9542       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9543       if(!status0)
9544         return false;
9545       const double *a(0),*bb(0),*be(0);
9546       if(typ1.isQuadratic())
9547         {
9548           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9549         }
9550       else
9551         {
9552           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9553         }
9554       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9555       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9556       return dist<eps;
9557     }
9558 }
9559
9560 /*!
9561  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9562  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9563  *
9564  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9565  */
9566 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9567 {
9568   if(candidatesIn2DEnd==candidatesIn2DBg)
9569     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9570   const double *coo(mesh2DSplit->getCoords()->begin());
9571   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9572     return *candidatesIn2DBg;
9573   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9574   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9575   if(cellIdInMesh1DSplitRelative<0)
9576     cur1D->changeOrientationOfCells();
9577   const int *c1D(cur1D->getNodalConnectivity()->begin());
9578   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9579   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9580     {
9581       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9582       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9583       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9584       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9585       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9586       for(unsigned it2=0;it2<sz;it2++)
9587         {
9588           INTERP_KERNEL::NormalizedCellType typeOfSon;
9589           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9590           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9591           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9592             return *it;
9593         }
9594     }
9595   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9596 }
9597
9598 /// @endcond
9599
9600 /*!
9601  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9602  * Thus the final result contains the aggregation of nodes of \a mesh2D, then nodes of \a mesh1D, then new nodes that are the result of the intersection
9603  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9604  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9605  *
9606  * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool. The mesh must be so that each point in the space covered by \a mesh2D
9607  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9608  * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D. \a mesh1D must be ordered consecutively. If it is not the case
9609  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9610  * \param [in] eps - precision used to perform intersections and localization operations.
9611  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9612  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9613  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9614  *                               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.
9615  * \param [out] cellIdInMesh1D - the array of pair that gives for each cell id \a i in \a splitMesh1D the cell in \a splitMesh2D on the left for the 1st component
9616  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9617  *                               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.
9618  *
9619  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9620  */
9621 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9622 {
9623   if(!mesh2D || !mesh1D)
9624     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9625   mesh2D->checkFullyDefined();
9626   mesh1D->checkFullyDefined();
9627   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9628   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9629     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9630   // Step 1: compute all edge intersections (new nodes)
9631   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9632   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9633   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9634   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9635   //
9636   // Build desc connectivity
9637   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9639   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9640   std::map<int,int> mergedNodes;
9641   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9642   // use mergeNodes to fix intersectEdge1
9643   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9644     {
9645       std::size_t n((*it0).size()/2);
9646       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9647       std::map<int,int>::const_iterator it1;
9648       it1=mergedNodes.find(eltStart);
9649       if(it1!=mergedNodes.end())
9650         (*it0)[0]=(*it1).second;
9651       it1=mergedNodes.find(eltEnd);
9652       if(it1!=mergedNodes.end())
9653         (*it0)[2*n-1]=(*it1).second;
9654     }
9655   //
9656   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9657   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9658   // Step 2: re-order newly created nodes according to the ordering found in m2
9659   std::vector< std::vector<int> > intersectEdge2;
9660   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9661   subDiv2.clear();
9662   // Step 3: compute splitMesh1D
9663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9664   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9665   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9666       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9667   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9669   // deal with cells in mesh2D that are not cut but only some of their edges are
9670   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9671   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9672   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9673   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9674   if(!idsInDesc2DToBeRefined->empty())
9675     {
9676       DataArrayInt *out0(0),*outi0(0);
9677       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9678       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9679       out0s=out0;
9680       out0s=out0s->buildUnique();
9681       out0s->sort(true);
9682     }
9683   //
9684   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9685   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9687   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9690   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9691     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9692   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9693   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9694   if((DataArrayInt *)out0s)
9695     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9696   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9697   // OK all is ready to insert in ret2 mesh
9698   if(!untouchedCells->empty())
9699     {// the most easy part, cells in mesh2D not impacted at all
9700       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9701       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9702       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9703     }
9704   if((DataArrayInt *)out0s)
9705     {// here dealing with cells in out0s but not in cellsToBeModified
9706       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9707       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9708       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9709         {
9710           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9711           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9712         }
9713       int offset(ret2->getNumberOfTuples());
9714       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9715       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9716       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9717       int kk(0),*ret3ptr(partOfRet3->getPointer());
9718       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9719         {
9720           int faceId(std::abs(*it)-1);
9721           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9722             {
9723               int tmp(fewModifiedCells->locateValue(*it2));
9724               if(tmp!=-1)
9725                 {
9726                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9727                     ret3ptr[2*kk]=tmp+offset;
9728                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9729                     ret3ptr[2*kk+1]=tmp+offset;
9730                 }
9731               else
9732                 {//the current edge is shared by a 2D cell that will be split just after
9733                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9734                     ret3ptr[2*kk]=-(*it2+1);
9735                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9736                     ret3ptr[2*kk+1]=-(*it2+1);
9737                 }
9738             }
9739         }
9740       m1Desc->setCoords(ret1->getCoords());
9741       ret1NonCol->setCoords(ret1->getCoords());
9742       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9743       if(!outMesh2DSplit.empty())
9744         {
9745           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9746           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9747             (*itt)->setCoords(da);
9748         }
9749     }
9750   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9751   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9752     {
9753       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9754       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9755       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9756       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9757       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9758       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9759       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9760       outMesh2DSplit.push_back(splitOfOneCell);
9761       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9762         ret2->pushBackSilent(*it);
9763     }
9764   //
9765   std::size_t nbOfMeshes(outMesh2DSplit.size());
9766   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9767   for(std::size_t i=0;i<nbOfMeshes;i++)
9768     tmp[i]=outMesh2DSplit[i];
9769   //
9770   ret1->getCoords()->setInfoOnComponents(compNames);
9771   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9772   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9773   ret3->rearrange(1);
9774   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9775   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9776     {
9777       int old2DCellId(-ret3->getIJ(*it,0)-1);
9778       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9779       ret3->setIJ(*it,0,FindRightCandidateAmong(ret2D,candidates->begin(),candidates->end(),ret1,*it%2==0?-((*it)/2+1):(*it)/2+1,eps));// div by 2 because 2 components natively in ret3
9780     }
9781   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9782   ret3->rearrange(2);
9783   //
9784   splitMesh1D=ret1.retn();
9785   splitMesh2D=ret2D.retn();
9786   cellIdInMesh2D=ret2.retn();
9787   cellIdInMesh1D=ret3.retn();
9788 }
9789
9790 /**
9791  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9792  * (newly created) nodes corresponding to the edge intersections.
9793  * Output params:
9794  * @param[out] cr, crI connectivity of the resulting mesh
9795  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9796  * TODO: describe input parameters
9797  */
9798 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9799                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9800                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9801                                                          const std::vector<double>& addCoords,
9802                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9803 {
9804   static const int SPACEDIM=2;
9805   const double *coo1(m1->getCoords()->getConstPointer());
9806   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9807   int offset1(m1->getNumberOfNodes());
9808   const double *coo2(m2->getCoords()->getConstPointer());
9809   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9810   int offset2(offset1+m2->getNumberOfNodes());
9811   int offset3(offset2+((int)addCoords.size())/2);
9812   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9813   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9814   // Here a BBTree on 2D-cells, not on segments:
9815   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9816   int ncell1(m1->getNumberOfCells());
9817   crI.push_back(0);
9818   for(int i=0;i<ncell1;i++)
9819     {
9820       std::vector<int> candidates2;
9821       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9822       std::map<INTERP_KERNEL::Node *,int> mapp;
9823       std::map<int,INTERP_KERNEL::Node *> mappRev;
9824       INTERP_KERNEL::QuadraticPolygon pol1;
9825       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9826       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9827       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9828       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9829       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9830       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9831           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9832       //
9833       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
9834       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9835       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9836       for(it1.first();!it1.finished();it1.next())
9837         edges1.insert(it1.current()->getPtr());
9838       //
9839       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9840       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9841       int ii=0;
9842       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9843         {
9844           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9845           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9846           // Complete mapping with elements coming from the current cell it2 in mesh2:
9847           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9848           // pol2 is the new QP in the final merged result.
9849           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9850               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9851         }
9852       ii=0;
9853       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9854         {
9855           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9856           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9857           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9858           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9859         }
9860       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9861       // by m2 but that we still want to keep in the final result.
9862       if(!edges1.empty())
9863         {
9864           try
9865           {
9866               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9867           }
9868           catch(INTERP_KERNEL::Exception& e)
9869           {
9870               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();
9871               throw INTERP_KERNEL::Exception(oss.str().c_str());
9872           }
9873         }
9874       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9875         (*it).second->decrRef();
9876     }
9877 }
9878
9879 /**
9880  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9881  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9882  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9883  * The caller is to deal with the resulting DataArrayInt.
9884  *  \throw If the coordinate array is not set.
9885  *  \throw If the nodal connectivity of the cells is not defined.
9886  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9887  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9888  *
9889  * \sa DataArrayInt::sortEachPairToMakeALinkedList
9890  */
9891 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9892 {
9893   checkFullyDefined();
9894   if(getMeshDimension()!=1)
9895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9896
9897   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9898   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9899   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9900   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9901   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9902   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9903   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9904   const int * dsi(_dsi->getConstPointer());
9905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9906   m_points=0;
9907   if (dsii->getNumberOfTuples())
9908     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9909
9910   int nc(getNumberOfCells());
9911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9912   result->alloc(nc,1);
9913
9914   // set of edges not used so far
9915   std::set<int> edgeSet;
9916   for (int i=0; i<nc; edgeSet.insert(i), i++);
9917
9918   int startSeg=0;
9919   int newIdx=0;
9920   // while we have points with only one neighbor segments
9921   do
9922     {
9923       std::list<int> linePiece;
9924       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9925       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9926         {
9927           // Fill the list forward (resp. backward) from the start segment:
9928           int activeSeg = startSeg;
9929           int prevPointId = -20;
9930           int ptId;
9931           while (!edgeSet.empty())
9932             {
9933               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9934                 {
9935                   if (direction==0)
9936                     linePiece.push_back(activeSeg);
9937                   else
9938                     linePiece.push_front(activeSeg);
9939                   edgeSet.erase(activeSeg);
9940                 }
9941
9942               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9943               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9944               if (dsi[ptId] == 1) // hitting the end of the line
9945                 break;
9946               prevPointId = ptId;
9947               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9948               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9949             }
9950         }
9951       // Done, save final piece into DA:
9952       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9953       newIdx += linePiece.size();
9954
9955       // identify next valid start segment (one which is not consumed)
9956       if(!edgeSet.empty())
9957         startSeg = *(edgeSet.begin());
9958     }
9959   while (!edgeSet.empty());
9960   return result.retn();
9961 }
9962
9963 /// @cond INTERNAL
9964
9965 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9966 {
9967   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9968   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9969   if(it==m.end())
9970     throw INTERP_KERNEL::Exception("Internal error in remapping !");
9971   int v((*it).second);
9972   if(v==forbVal0 || v==forbVal1)
9973     return ;
9974   if(std::find(isect.begin(),isect.end(),v)==isect.end())
9975     isect.push_back(v);
9976 }
9977
9978 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9979 {
9980   int sz(c.size());
9981   if(sz<=1)
9982     return false;
9983   bool presenceOfOn(false);
9984   for(int i=0;i<sz;i++)
9985     {
9986       INTERP_KERNEL::ElementaryEdge *e(c[i]);
9987       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9988         continue ;
9989       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9990       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9991     }
9992   return presenceOfOn;
9993 }
9994
9995 /// @endcond
9996
9997 /**
9998  * 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.
9999  * 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.
10000  * 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.
10001  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10002  *
10003  * \return int - the number of new nodes created (in most of cases 0).
10004  * 
10005  * \throw If \a this is not coherent.
10006  * \throw If \a this has not spaceDim equal to 2.
10007  * \throw If \a this has not meshDim equal to 2.
10008  * \throw If some subcells needed to be split are orphan.
10009  * \sa MEDCouplingUMesh::conformize2D
10010  */
10011 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10012 {
10013   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10014     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10015   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10016   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10017     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10018   if(midOpt==0 && midOptI==0)
10019     {
10020       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10021       return 0;
10022     }
10023   else if(midOpt!=0 && midOptI!=0)
10024     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10025   else
10026     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10027 }
10028
10029 /*!
10030  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10031  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10032  * 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
10033  * 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).
10034  * 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.
10035  * 
10036  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10037  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10038  *
10039  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10040  * This method expects that all nodes in \a this are not closer than \a eps.
10041  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10042  * 
10043  * \param [in] eps the relative error to detect merged edges.
10044  * \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
10045  *                           that the user is expected to deal with.
10046  *
10047  * \throw If \a this is not coherent.
10048  * \throw If \a this has not spaceDim equal to 2.
10049  * \throw If \a this has not meshDim equal to 2.
10050  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10051  */
10052 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10053 {
10054   static const int SPACEDIM=2;
10055   checkCoherency();
10056   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10057     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10058   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10059   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10060   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10061   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10062   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10063   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10064   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10065   std::vector<double> addCoo;
10066   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10067   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10068   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10069   for(int i=0;i<nDescCell;i++)
10070     {
10071       std::vector<int> candidates;
10072       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10073       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10074         if(*it>i)
10075           {
10076             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10077             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10078                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10079             INTERP_KERNEL::MergePoints merge;
10080             INTERP_KERNEL::QuadraticPolygon c1,c2;
10081             e1->intersectWith(e2,merge,c1,c2);
10082             e1->decrRef(); e2->decrRef();
10083             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10084               overlapEdge[i].push_back(*it);
10085             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10086               overlapEdge[*it].push_back(i);
10087           }
10088     }
10089   // splitting done. sort intersect point in intersectEdge.
10090   std::vector< std::vector<int> > middle(nDescCell);
10091   int nbOf2DCellsToBeSplit(0);
10092   bool middleNeedsToBeUsed(false);
10093   std::vector<bool> cells2DToTreat(nDescCell,false);
10094   for(int i=0;i<nDescCell;i++)
10095     {
10096       std::vector<int>& isect(intersectEdge[i]);
10097       int sz((int)isect.size());
10098       if(sz>1)
10099         {
10100           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10101           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10102           e->sortSubNodesAbs(coords,isect);
10103           e->decrRef();
10104         }
10105       if(sz!=0)
10106         {
10107           int idx0(rdi[i]),idx1(rdi[i+1]);
10108           if(idx1-idx0!=1)
10109             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10110           if(!cells2DToTreat[rd[idx0]])
10111             {
10112               cells2DToTreat[rd[idx0]]=true;
10113               nbOf2DCellsToBeSplit++;
10114             }
10115           // try to reuse at most eventual 'middle' of SEG3
10116           std::vector<int>& mid(middle[i]);
10117           mid.resize(sz+1,-1);
10118           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10119             {
10120               middleNeedsToBeUsed=true;
10121               const std::vector<int>& candidates(overlapEdge[i]);
10122               std::vector<int> trueCandidates;
10123               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10124                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10125                   trueCandidates.push_back(*itc);
10126               int stNode(c[ci[i]+1]),endNode(isect[0]);
10127               for(int j=0;j<sz+1;j++)
10128                 {
10129                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10130                     {
10131                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10132                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10133                         { mid[j]=*itc; break; }
10134                     }
10135                   stNode=endNode;
10136                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10137                 }
10138             }
10139         }
10140     }
10141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10142   if(nbOf2DCellsToBeSplit==0)
10143     return ret.retn();
10144   //
10145   int *retPtr(ret->getPointer());
10146   for(int i=0;i<nCell;i++)
10147     if(cells2DToTreat[i])
10148       *retPtr++=i;
10149   //
10150   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10151   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10152   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10153   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10154   if(middleNeedsToBeUsed)
10155     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10156   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10157   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10158   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.
10159   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10160   {
10161     bool areNodesMerged; int newNbOfNodes;
10162     if(nbOfNodesCreated!=0)
10163       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10164   }
10165   return ret.retn();
10166 }
10167
10168 /*!
10169  * 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.
10170  * 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).
10171  * 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
10172  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10173  * 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
10174  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10175  *
10176  * 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
10177  * using new instance, idem for coordinates.
10178  *
10179  * 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.
10180  * 
10181  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10182  *
10183  * \throw If \a this is not coherent.
10184  * \throw If \a this has not spaceDim equal to 2.
10185  * \throw If \a this has not meshDim equal to 2.
10186  * 
10187  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10188  */
10189 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10190 {
10191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10192   checkCoherency();
10193   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10194     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10195   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10196   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10197   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10198   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10200   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10201   const double *coords(_coords->begin());
10202   int *newciptr(newci->getPointer());
10203   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10204     {
10205       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10206         ret->pushBackSilent(i);
10207       newciptr[1]=newc->getNumberOfTuples();
10208     }
10209   //
10210   if(ret->empty())
10211     return ret.retn();
10212   if(!appendedCoords->empty())
10213     {
10214       appendedCoords->rearrange(2);
10215       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10216       //non const part
10217       setCoords(newCoords);
10218     }
10219   //non const part
10220   setConnectivity(newc,newci,true);
10221   return ret.retn();
10222 }
10223
10224 /*!
10225  * \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.
10226  *                               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.
10227  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10228  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10229  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10230  * \param [out] addCoo - nodes to be append at the end
10231  * \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.
10232  */
10233 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10234                                          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)
10235 {
10236   static const int SPACEDIM=2;
10237   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10238   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10239   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10240   // Build BB tree of all edges in the tool mesh (second mesh)
10241   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10242   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10243   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10244   intersectEdge1.resize(nDescCell1);
10245   colinear2.resize(nDescCell2);
10246   subDiv2.resize(nDescCell2);
10247   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10248
10249   std::vector<int> candidates1(1);
10250   int offset1(m1Desc->getNumberOfNodes());
10251   int offset2(offset1+m2Desc->getNumberOfNodes());
10252   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10253     {
10254       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10255       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10256       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10257         {
10258           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10259           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10260           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10261           candidates1[0]=i;
10262           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10263           // 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
10264           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10265           std::set<INTERP_KERNEL::Node *> nodes;
10266           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10267           std::size_t szz(nodes.size());
10268           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10269           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10270           for(std::size_t iii=0;iii<szz;iii++,itt++)
10271             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10272           // end of protection
10273           // Performs egde cutting:
10274           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10275           delete pol2;
10276           delete pol1;
10277         }
10278       else
10279         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10280         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10281     }
10282 }
10283
10284 /*!
10285  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10286  * It builds the descending connectivity of the two meshes, and then using a binary tree
10287  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10288  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10289  */
10290 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10291                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10292                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10293                                                    std::vector<double>& addCoo,
10294                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10295 {
10296   // Build desc connectivity
10297   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10298   desc2=DataArrayInt::New();
10299   descIndx2=DataArrayInt::New();
10300   revDesc2=DataArrayInt::New();
10301   revDescIndx2=DataArrayInt::New();
10302   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10303   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10304   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10305   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10306   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10307   std::map<int,int> notUsedMap;
10308   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10309   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10310   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10311 }
10312
10313 /*!
10314  * This method performs the 2nd step of Partition of 2D mesh.
10315  * This method has 4 inputs :
10316  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10317  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10318  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10319  * 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'
10320  * Nodes end up lying consecutively on a cutted edge.
10321  * \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.
10322  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10323  * \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.
10324  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10325  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10326  */
10327 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10328                                            const std::vector<double>& addCoo,
10329                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10330 {
10331   int offset1=m1->getNumberOfNodes();
10332   int ncell=m2->getNumberOfCells();
10333   const int *c=m2->getNodalConnectivity()->getConstPointer();
10334   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10335   const double *coo=m2->getCoords()->getConstPointer();
10336   const double *cooBis=m1->getCoords()->getConstPointer();
10337   int offset2=offset1+m2->getNumberOfNodes();
10338   intersectEdge.resize(ncell);
10339   for(int i=0;i<ncell;i++,cI++)
10340     {
10341       const std::vector<int>& divs=subDiv[i];
10342       int nnode=cI[1]-cI[0]-1;
10343       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10344       std::map<INTERP_KERNEL::Node *, int> mapp22;
10345       for(int j=0;j<nnode;j++)
10346         {
10347           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10348           int nnid=c[(*cI)+j+1];
10349           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10350           mapp22[nn]=nnid+offset1;
10351         }
10352       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10353       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10354         ((*it).second.first)->decrRef();
10355       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10356       std::map<INTERP_KERNEL::Node *,int> mapp3;
10357       for(std::size_t j=0;j<divs.size();j++)
10358         {
10359           int id=divs[j];
10360           INTERP_KERNEL::Node *tmp=0;
10361           if(id<offset1)
10362             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10363           else if(id<offset2)
10364             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10365           else
10366             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10367           addNodes[j]=tmp;
10368           mapp3[tmp]=id;
10369         }
10370       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10371       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10372         (*it)->decrRef();
10373       e->decrRef();
10374     }
10375 }
10376
10377 /*!
10378  * 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).
10379  * 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
10380  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10381  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10382  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10383  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10384  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10385  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10386  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10387  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10388  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10389  * \param [out] cut3DSuf input/output param.
10390  */
10391 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10392                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10393                                                    const int *desc, const int *descIndx, 
10394                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10395 {
10396   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10397   int nbOf3DSurfCell=(int)cut3DSurf.size();
10398   for(int i=0;i<nbOf3DSurfCell;i++)
10399     {
10400       std::vector<int> res;
10401       int offset=descIndx[i];
10402       int nbOfSeg=descIndx[i+1]-offset;
10403       for(int j=0;j<nbOfSeg;j++)
10404         {
10405           int edgeId=desc[offset+j];
10406           int status=cut3DCurve[edgeId];
10407           if(status!=-2)
10408             {
10409               if(status>-1)
10410                 res.push_back(status);
10411               else
10412                 {
10413                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10414                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10415                 }
10416             }
10417         }
10418       switch(res.size())
10419       {
10420         case 2:
10421           {
10422             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10423             break;
10424           }
10425         case 1:
10426         case 0:
10427           {
10428             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10429             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10430             if(res.size()==2)
10431               {
10432                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10433               }
10434             else
10435               {
10436                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10437               }
10438             break;
10439           }
10440         default:
10441           {// case when plane is on a multi colinear edge of a polyhedron
10442             if((int)res.size()==2*nbOfSeg)
10443               {
10444                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10445               }
10446             else
10447               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10448           }
10449       }
10450     }
10451 }
10452
10453 /*!
10454  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10455  * 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).
10456  * 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
10457  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10458  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10459  * \param desc is the descending connectivity 3D->3DSurf
10460  * \param descIndx is the descending connectivity index 3D->3DSurf
10461  */
10462 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10463                                                   const int *desc, const int *descIndx,
10464                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10465 {
10466   checkFullyDefined();
10467   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10469   const int *nodal3D=_nodal_connec->getConstPointer();
10470   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10471   int nbOfCells=getNumberOfCells();
10472   for(int i=0;i<nbOfCells;i++)
10473     {
10474       std::map<int, std::set<int> > m;
10475       int offset=descIndx[i];
10476       int nbOfFaces=descIndx[i+1]-offset;
10477       int start=-1;
10478       int end=-1;
10479       for(int j=0;j<nbOfFaces;j++)
10480         {
10481           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10482           if(p.first!=-1 && p.second!=-1)
10483             {
10484               if(p.first!=-2)
10485                 {
10486                   start=p.first; end=p.second;
10487                   m[p.first].insert(p.second);
10488                   m[p.second].insert(p.first);
10489                 }
10490               else
10491                 {
10492                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10493                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10494                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10495                   INTERP_KERNEL::NormalizedCellType cmsId;
10496                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10497                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10498                   for(unsigned k=0;k<nbOfNodesSon;k++)
10499                     {
10500                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10501                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10502                     }
10503                 }
10504             }
10505         }
10506       if(m.empty())
10507         continue;
10508       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10509       int prev=end;
10510       while(end!=start)
10511         {
10512           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10513           const std::set<int>& s=(*it).second;
10514           std::set<int> s2; s2.insert(prev);
10515           std::set<int> s3;
10516           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10517           if(s3.size()==1)
10518             {
10519               int val=*s3.begin();
10520               conn.push_back(start);
10521               prev=start;
10522               start=val;
10523             }
10524           else
10525             start=end;
10526         }
10527       conn.push_back(end);
10528       if(conn.size()>3)
10529         {
10530           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10531           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10532           cellIds->pushBackSilent(i);
10533         }
10534     }
10535 }
10536
10537 /*!
10538  * 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
10539  * 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
10540  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10541  * 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
10542  * 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.
10543  * 
10544  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10545  */
10546 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10547 {
10548   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10549   if(sz>=4)
10550     {
10551       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10552       if(cm.getDimension()==2)
10553         {
10554           const int *node=nodalConnBg+1;
10555           int startNode=*node++;
10556           double refX=coords[2*startNode];
10557           for(;node!=nodalConnEnd;node++)
10558             {
10559               if(coords[2*(*node)]<refX)
10560                 {
10561                   startNode=*node;
10562                   refX=coords[2*startNode];
10563                 }
10564             }
10565           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10566           refX=1e300;
10567           double tmp1;
10568           double tmp2[2];
10569           double angle0=-M_PI/2;
10570           //
10571           int nextNode=-1;
10572           int prevNode=-1;
10573           double resRef;
10574           double angleNext=0.;
10575           while(nextNode!=startNode)
10576             {
10577               nextNode=-1;
10578               resRef=1e300;
10579               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10580                 {
10581                   if(*node!=tmpOut.back() && *node!=prevNode)
10582                     {
10583                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10584                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10585                       double res;
10586                       if(angleM<=angle0)
10587                         res=angle0-angleM;
10588                       else
10589                         res=angle0-angleM+2.*M_PI;
10590                       if(res<resRef)
10591                         {
10592                           nextNode=*node;
10593                           resRef=res;
10594                           angleNext=angleM;
10595                         }
10596                     }
10597                 }
10598               if(nextNode!=startNode)
10599                 {
10600                   angle0=angleNext-M_PI;
10601                   if(angle0<-M_PI)
10602                     angle0+=2*M_PI;
10603                   prevNode=tmpOut.back();
10604                   tmpOut.push_back(nextNode);
10605                 }
10606             }
10607           std::vector<int> tmp3(2*(sz-1));
10608           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10609           std::copy(nodalConnBg+1,nodalConnEnd,it);
10610           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10611             {
10612               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10613               return false;
10614             }
10615           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10616             {
10617               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10618               return false;
10619             }
10620           else
10621             {
10622               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10623               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10624               return true;
10625             }
10626         }
10627       else
10628         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10629     }
10630   else
10631     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10632 }
10633
10634 /*!
10635  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10636  * 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.
10637  * 
10638  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10639  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10640  * \param [in,out] arr array in which the remove operation will be done.
10641  * \param [in,out] arrIndx array in the remove operation will modify
10642  * \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])
10643  * \return true if \b arr and \b arrIndx have been modified, false if not.
10644  */
10645 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10646 {
10647   if(!arrIndx || !arr)
10648     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10649   if(offsetForRemoval<0)
10650     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10651   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10652   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10653   int *arrIPtr=arrIndx->getPointer();
10654   *arrIPtr++=0;
10655   int previousArrI=0;
10656   const int *arrPtr=arr->getConstPointer();
10657   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10658   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10659     {
10660       if(*arrIPtr-previousArrI>offsetForRemoval)
10661         {
10662           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10663             {
10664               if(s.find(*work)==s.end())
10665                 arrOut.push_back(*work);
10666             }
10667         }
10668       previousArrI=*arrIPtr;
10669       *arrIPtr=(int)arrOut.size();
10670     }
10671   if(arr->getNumberOfTuples()==(int)arrOut.size())
10672     return false;
10673   arr->alloc((int)arrOut.size(),1);
10674   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10675   return true;
10676 }
10677
10678 /*!
10679  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10680  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10681  * The selection of extraction is done standardly in new2old format.
10682  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10683  *
10684  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10685  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10686  * \param [in] arrIn arr origin array from which the extraction will be done.
10687  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10688  * \param [out] arrOut the resulting array
10689  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10690  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10691  */
10692 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10693                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10694 {
10695   if(!arrIn || !arrIndxIn)
10696     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10697   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10698   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10700   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10701   const int *arrInPtr=arrIn->getConstPointer();
10702   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10703   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10704   if(nbOfGrps<0)
10705     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10706   int maxSizeOfArr=arrIn->getNumberOfTuples();
10707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10708   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10709   arrIo->alloc((int)(sz+1),1);
10710   const int *idsIt=idsOfSelectBg;
10711   int *work=arrIo->getPointer();
10712   *work++=0;
10713   int lgth=0;
10714   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10715     {
10716       if(*idsIt>=0 && *idsIt<nbOfGrps)
10717         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10718       else
10719         {
10720           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10721           throw INTERP_KERNEL::Exception(oss.str().c_str());
10722         }
10723       if(lgth>=work[-1])
10724         *work=lgth;
10725       else
10726         {
10727           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10728           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10729           throw INTERP_KERNEL::Exception(oss.str().c_str());
10730         }
10731     }
10732   arro->alloc(lgth,1);
10733   work=arro->getPointer();
10734   idsIt=idsOfSelectBg;
10735   for(std::size_t i=0;i<sz;i++,idsIt++)
10736     {
10737       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10738         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10739       else
10740         {
10741           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10742           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10743           throw INTERP_KERNEL::Exception(oss.str().c_str());
10744         }
10745     }
10746   arrOut=arro.retn();
10747   arrIndexOut=arrIo.retn();
10748 }
10749
10750 /*!
10751  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10752  * 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 ).
10753  * The selection of extraction is done standardly in new2old format.
10754  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10755  *
10756  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10757  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10758  * \param [in] arrIn arr origin array from which the extraction will be done.
10759  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10760  * \param [out] arrOut the resulting array
10761  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10762  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10763  */
10764 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10765                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10766 {
10767   if(!arrIn || !arrIndxIn)
10768     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10769   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10770   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10771     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10772   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10773   const int *arrInPtr=arrIn->getConstPointer();
10774   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10775   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10776   if(nbOfGrps<0)
10777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10778   int maxSizeOfArr=arrIn->getNumberOfTuples();
10779   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10780   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10781   arrIo->alloc((int)(sz+1),1);
10782   int idsIt=idsOfSelectStart;
10783   int *work=arrIo->getPointer();
10784   *work++=0;
10785   int lgth=0;
10786   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10787     {
10788       if(idsIt>=0 && idsIt<nbOfGrps)
10789         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10790       else
10791         {
10792           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10793           throw INTERP_KERNEL::Exception(oss.str().c_str());
10794         }
10795       if(lgth>=work[-1])
10796         *work=lgth;
10797       else
10798         {
10799           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10800           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10801           throw INTERP_KERNEL::Exception(oss.str().c_str());
10802         }
10803     }
10804   arro->alloc(lgth,1);
10805   work=arro->getPointer();
10806   idsIt=idsOfSelectStart;
10807   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10808     {
10809       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10810         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10811       else
10812         {
10813           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10814           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10815           throw INTERP_KERNEL::Exception(oss.str().c_str());
10816         }
10817     }
10818   arrOut=arro.retn();
10819   arrIndexOut=arrIo.retn();
10820 }
10821
10822 /*!
10823  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10824  * 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
10825  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10826  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10827  *
10828  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10829  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10830  * \param [in] arrIn arr origin array from which the extraction will be done.
10831  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10832  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10833  * \param [in] srcArrIndex index array of \b srcArr
10834  * \param [out] arrOut the resulting array
10835  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10836  * 
10837  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10838  */
10839 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10840                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10841                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10842 {
10843   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10844     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10847   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10848   std::vector<bool> v(nbOfTuples,true);
10849   int offset=0;
10850   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10851   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10852   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10853     {
10854       if(*it>=0 && *it<nbOfTuples)
10855         {
10856           v[*it]=false;
10857           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10858         }
10859       else
10860         {
10861           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10862           throw INTERP_KERNEL::Exception(oss.str().c_str());
10863         }
10864     }
10865   srcArrIndexPtr=srcArrIndex->getConstPointer();
10866   arrIo->alloc(nbOfTuples+1,1);
10867   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10868   const int *arrInPtr=arrIn->getConstPointer();
10869   const int *srcArrPtr=srcArr->getConstPointer();
10870   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10871   int *arroPtr=arro->getPointer();
10872   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10873     {
10874       if(v[ii])
10875         {
10876           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10877           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10878         }
10879       else
10880         {
10881           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10882           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10883           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10884         }
10885     }
10886   arrOut=arro.retn();
10887   arrIndexOut=arrIo.retn();
10888 }
10889
10890 /*!
10891  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10892  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10893  *
10894  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10895  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10896  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10897  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10898  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10899  * \param [in] srcArrIndex index array of \b srcArr
10900  * 
10901  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10902  */
10903 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10904                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10905 {
10906   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10908   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10909   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10910   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10911   int *arrInOutPtr=arrInOut->getPointer();
10912   const int *srcArrPtr=srcArr->getConstPointer();
10913   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10914     {
10915       if(*it>=0 && *it<nbOfTuples)
10916         {
10917           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10918             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10919           else
10920             {
10921               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] !";
10922               throw INTERP_KERNEL::Exception(oss.str().c_str());
10923             }
10924         }
10925       else
10926         {
10927           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10928           throw INTERP_KERNEL::Exception(oss.str().c_str());
10929         }
10930     }
10931 }
10932
10933 /*!
10934  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10935  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10936  * 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]].
10937  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10938  * A negative value in \b arrIn means that it is ignored.
10939  * 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.
10940  * 
10941  * \param [in] arrIn arr origin array from which the extraction will be done.
10942  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10943  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10944  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10945  */
10946 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10947 {
10948   int seed=0,nbOfDepthPeelingPerformed=0;
10949   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10950 }
10951
10952 /*!
10953  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10954  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10955  * 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]].
10956  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10957  * A negative value in \b arrIn means that it is ignored.
10958  * 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.
10959  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10960  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10961  * \param [in] arrIn arr origin array from which the extraction will be done.
10962  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10963  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10964  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10965  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10966  * \sa MEDCouplingUMesh::partitionBySpreadZone
10967  */
10968 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10969 {
10970   nbOfDepthPeelingPerformed=0;
10971   if(!arrIndxIn)
10972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10973   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10974   if(nbOfTuples<=0)
10975     {
10976       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10977       return ret;
10978     }
10979   //
10980   std::vector<bool> fetched(nbOfTuples,false);
10981   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10982 }
10983
10984 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10985 {
10986   nbOfDepthPeelingPerformed=0;
10987   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10988     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10989   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10990   std::vector<bool> fetched2(nbOfTuples,false);
10991   int i=0;
10992   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10993     {
10994       if(*seedElt>=0 && *seedElt<nbOfTuples)
10995         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10996       else
10997         { 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()); }
10998     }
10999   const int *arrInPtr=arrIn->getConstPointer();
11000   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11001   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11002   std::vector<int> idsToFetch1(seedBg,seedEnd);
11003   std::vector<int> idsToFetch2;
11004   std::vector<int> *idsToFetch=&idsToFetch1;
11005   std::vector<int> *idsToFetchOther=&idsToFetch2;
11006   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11007     {
11008       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11009         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11010           if(!fetched[*it2])
11011             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11012       std::swap(idsToFetch,idsToFetchOther);
11013       idsToFetchOther->clear();
11014       nbOfDepthPeelingPerformed++;
11015     }
11016   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11017   i=0;
11018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11019   int *retPtr=ret->getPointer();
11020   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11021     if(*it)
11022       *retPtr++=i;
11023   return ret.retn();
11024 }
11025
11026 /*!
11027  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11028  * 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
11029  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11030  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11031  *
11032  * \param [in] start begin of set of ids of the input extraction (included)
11033  * \param [in] end end of set of ids of the input extraction (excluded)
11034  * \param [in] step step of the set of ids in range mode.
11035  * \param [in] arrIn arr origin array from which the extraction will be done.
11036  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11037  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11038  * \param [in] srcArrIndex index array of \b srcArr
11039  * \param [out] arrOut the resulting array
11040  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11041  * 
11042  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11043  */
11044 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11045                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11046                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11047 {
11048   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11051   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11052   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11053   int offset=0;
11054   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11055   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11056   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11057   int it=start;
11058   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11059     {
11060       if(it>=0 && it<nbOfTuples)
11061         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11062       else
11063         {
11064           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11065           throw INTERP_KERNEL::Exception(oss.str().c_str());
11066         }
11067     }
11068   srcArrIndexPtr=srcArrIndex->getConstPointer();
11069   arrIo->alloc(nbOfTuples+1,1);
11070   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11071   const int *arrInPtr=arrIn->getConstPointer();
11072   const int *srcArrPtr=srcArr->getConstPointer();
11073   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11074   int *arroPtr=arro->getPointer();
11075   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11076     {
11077       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11078       if(pos<0)
11079         {
11080           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11081           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11082         }
11083       else
11084         {
11085           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11086           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11087         }
11088     }
11089   arrOut=arro.retn();
11090   arrIndexOut=arrIo.retn();
11091 }
11092
11093 /*!
11094  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11095  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11096  *
11097  * \param [in] start begin of set of ids of the input extraction (included)
11098  * \param [in] end end of set of ids of the input extraction (excluded)
11099  * \param [in] step step of the set of ids in range mode.
11100  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11101  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11102  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11103  * \param [in] srcArrIndex index array of \b srcArr
11104  * 
11105  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11106  */
11107 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11108                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11109 {
11110   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11112   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11113   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11114   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11115   int *arrInOutPtr=arrInOut->getPointer();
11116   const int *srcArrPtr=srcArr->getConstPointer();
11117   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11118   int it=start;
11119   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11120     {
11121       if(it>=0 && it<nbOfTuples)
11122         {
11123           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11124             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11125           else
11126             {
11127               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11128               throw INTERP_KERNEL::Exception(oss.str().c_str());
11129             }
11130         }
11131       else
11132         {
11133           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11134           throw INTERP_KERNEL::Exception(oss.str().c_str());
11135         }
11136     }
11137 }
11138
11139 /*!
11140  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11141  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11142  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11143  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11144  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11145  * 
11146  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11147  */
11148 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11149 {
11150   checkFullyDefined();
11151   int mdim=getMeshDimension();
11152   int spaceDim=getSpaceDimension();
11153   if(mdim!=spaceDim)
11154     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11155   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11156   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11157   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11158   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11159   ret->setCoords(getCoords());
11160   ret->allocateCells((int)partition.size());
11161   //
11162   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11163     {
11164       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11165       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11166       switch(mdim)
11167       {
11168         case 2:
11169           cell=tmp->buildUnionOf2DMesh();
11170           break;
11171         case 3:
11172           cell=tmp->buildUnionOf3DMesh();
11173           break;
11174         default:
11175           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11176       }
11177
11178       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11179     }
11180   //
11181   ret->finishInsertingCells();
11182   return ret.retn();
11183 }
11184
11185 /*!
11186  * This method partitions \b this into contiguous zone.
11187  * This method only needs a well defined connectivity. Coordinates are not considered here.
11188  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11189  */
11190 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11191 {
11192   int nbOfCellsCur=getNumberOfCells();
11193   std::vector<DataArrayInt *> ret;
11194   if(nbOfCellsCur<=0)
11195     return ret;
11196   DataArrayInt *neigh=0,*neighI=0;
11197   computeNeighborsOfCells(neigh,neighI);
11198   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11199   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11200   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11201   int seed=0;
11202   while(seed<nbOfCellsCur)
11203     {
11204       int nbOfPeelPerformed=0;
11205       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11206       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11207     }
11208   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11209     ret.push_back((*it).retn());
11210   return ret;
11211 }
11212
11213 /*!
11214  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11215  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11216  *
11217  * \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.
11218  * \return a newly allocated DataArrayInt to be managed by the caller.
11219  * \throw In case of \a code has not the right format (typically of size 3*n)
11220  */
11221 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11222 {
11223   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11224   std::size_t nb=code.size()/3;
11225   if(code.size()%3!=0)
11226     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11227   ret->alloc((int)nb,2);
11228   int *retPtr=ret->getPointer();
11229   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11230     {
11231       retPtr[0]=code[3*i+2];
11232       retPtr[1]=code[3*i+2]+code[3*i+1];
11233     }
11234   return ret.retn();
11235 }
11236
11237 /*!
11238  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11239  * All cells in \a this are expected to be linear 3D cells.
11240  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11241  * It leads to an increase to number of cells.
11242  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11243  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11244  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11245  *
11246  * \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.
11247  *                      For all other cells, the splitting policy will be ignored.
11248  * \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. 
11249  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11250  *          an id of old cell producing it. The caller is to delete this array using
11251  *         decrRef() as it is no more needed.
11252  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11253  *
11254  * \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
11255  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11256  * 
11257  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11258  * \throw If \a this is not fully constituted with linear 3D cells.
11259  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11260  */
11261 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11262 {
11263   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11264   checkConnectivityFullyDefined();
11265   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11267   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11268   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11269   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11270   int *retPt(ret->getPointer());
11271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11272   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11273   const int *oldc(_nodal_connec->begin());
11274   const int *oldci(_nodal_connec_index->begin());
11275   const double *coords(_coords->begin());
11276   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11277     {
11278       std::vector<int> a; std::vector<double> b;
11279       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11280       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11281       const int *aa(&a[0]);
11282       if(!b.empty())
11283         {
11284           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11285             if(*it<0)
11286               *it=(-(*(it))-1+nbNodes);
11287           addPts->insertAtTheEnd(b.begin(),b.end());
11288           nbNodes+=(int)b.size()/3;
11289         }
11290       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11291         newConn->insertAtTheEnd(aa,aa+4);
11292     }
11293   if(!addPts->empty())
11294     {
11295       addPts->rearrange(3);
11296       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11297       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11298       ret0->setCoords(addPts);
11299     }
11300   else
11301     {
11302       nbOfAdditionalPoints=0;
11303       ret0->setCoords(getCoords());
11304     }
11305   ret0->setNodalConnectivity(newConn);
11306   //
11307   ret->computeOffsets2();
11308   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11309   return ret0.retn();
11310 }
11311
11312 /*!
11313  * 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). 
11314  *
11315  * \sa MEDCouplingUMesh::split2DCells
11316  */
11317 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11318 {
11319   checkConnectivityFullyDefined();
11320   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11322   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11323   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11324   int prevPosOfCi(ciPtr[0]);
11325   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11326     {
11327       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11328       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11329       for(int j=0;j<sz;j++)
11330         {
11331           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11332           for(int k=0;k<sz2;k++)
11333             *cPtr++=subPtr[offset2+k];
11334           if(j!=sz-1)
11335             *cPtr++=oldConn[prevPosOfCi+j+2];
11336           deltaSz+=sz2;
11337         }
11338       prevPosOfCi=ciPtr[1];
11339       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11340     }
11341   if(c->end()!=cPtr)
11342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11343   _nodal_connec->decrRef();
11344   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11345 }
11346
11347 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11348 {
11349   if(id!=-1)
11350     return id;
11351   else
11352     {
11353       int ret(nodesCnter++);
11354       double newPt[2];
11355       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11356       addCoo.insertAtTheEnd(newPt,newPt+2);
11357       return ret;
11358     }
11359 }
11360
11361 /// @cond INTERNAL
11362
11363 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)
11364 {
11365   int tmp[3];
11366   int trueStart(start>=0?start:nbOfEdges+start);
11367   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11368   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11369   if(linOrArc)
11370     {
11371       if(stp-start>1)
11372         {
11373           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11374           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11375           middles.push_back(tmp3+offset);
11376         }
11377       else
11378         middles.push_back(connBg[trueStart+nbOfEdges]);
11379     }
11380 }
11381
11382 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)
11383 {
11384   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11385   newConnOfCell->pushBackSilent(tmpEnd);
11386   if(linOrArc)
11387     {
11388       if(stp-start>1)
11389         {
11390           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11391           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11392           middles.push_back(tmp3+offset);
11393         }
11394       else
11395         middles.push_back(connBg[start+nbOfEdges]);
11396     }
11397 }
11398
11399 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)
11400 {
11401   if(linOrArc)
11402     {
11403       if(stp-start>1)
11404         {
11405           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11406           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11407           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11408           middles.push_back(tmp3+offset);
11409         }
11410       else
11411         middles.push_back(connBg[start+nbOfEdges]);
11412     }
11413 }
11414
11415 /// @cond INTERNAL
11416
11417 /*!
11418  * 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 ) .
11419  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11420  */
11421 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11422 {
11423   std::size_t sz(std::distance(connBg,connEnd));
11424   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11426   sz--;
11427   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11428   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11429   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11430   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11431   INTERP_KERNEL::NormalizedCellType typeOfSon;
11432   std::vector<int> middles;
11433   bool ret(false);
11434   for(;nbOfHit<nbs;nbOfTurn++)
11435     {
11436       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11437       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11438       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11439       posEndElt++;
11440       nbOfHit++;
11441       unsigned endI(nbs-nbOfHit);
11442       for(unsigned i=0;i<endI;i++)
11443         {
11444           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11445           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11446           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11447           bool isColinear(eint->areColinears());
11448           if(isColinear)
11449             {
11450               nbOfHit++;
11451               posEndElt++;
11452               ret=true;
11453             }
11454           delete eint;
11455           eCand->decrRef();
11456           if(!isColinear)
11457             {
11458               if(nbOfTurn==0)
11459                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11460                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11461                   for(unsigned ii=0;ii<endII;ii++)
11462                     {
11463                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11464                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11465                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11466                       isColinear=eint->areColinears();
11467                       if(isColinear)
11468                         {
11469                           nbOfHit++;
11470                           posBaseElt--;
11471                           ret=true;
11472                         }
11473                       delete eint;
11474                       eCand->decrRef();
11475                       if(!isColinear)
11476                         break;
11477                     }
11478                 }
11479               break;
11480             }
11481         }
11482       //push [posBaseElt,posEndElt) in newConnOfCell using e
11483       if(nbOfTurn==0)
11484         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11485       else if(nbOfHit!=nbs)
11486         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11487       else
11488         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11489       posBaseElt=posEndElt;
11490       e->decrRef();
11491     }
11492   if(!middles.empty())
11493     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11494   return ret;
11495 }
11496
11497 /*!
11498  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11499  *
11500  * \return  int - the number of new nodes created.
11501  * \sa MEDCouplingUMesh::split2DCells
11502  */
11503 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11504 {
11505   checkCoherency();
11506   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11507   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11508   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11509   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11510   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11511   const double *oldCoordsPtr(getCoords()->begin());
11512   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11513   int prevPosOfCi(ciPtr[0]);
11514   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11515     {
11516       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11517       for(int j=0;j<sz;j++)
11518         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11519       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11520       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11521         {
11522           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11523           if(sz2==0)
11524             {
11525               if(j<sz-1)
11526                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11527               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11528               continue;
11529             }
11530           std::vector<INTERP_KERNEL::Node *> ns(3);
11531           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11532           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11533           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11534           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11535           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11536             {
11537               cPtr[1]=subPtr[offset2+k];
11538               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11539             }
11540           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11541           if(j!=sz-1)
11542             { cPtr[1]=tmpEnd; }
11543           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11544         }
11545       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11546       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11547     }
11548   if(c->end()!=cPtr)
11549     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11550   _nodal_connec->decrRef();
11551   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11552   addCoo->rearrange(2);
11553   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11554   setCoords(coo);
11555   return addCoo->getNumberOfTuples();
11556 }
11557
11558 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11559 {
11560   if(nodalConnec && nodalConnecIndex)
11561     {
11562       types.clear();
11563       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11564       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11565       if(nbOfElem>0)
11566         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11567           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11568     }
11569 }
11570
11571 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11572     _own_cell(true),_cell_id(-1),_nb_cell(0)
11573 {
11574   if(mesh)
11575     {
11576       mesh->incrRef();
11577       _nb_cell=mesh->getNumberOfCells();
11578     }
11579 }
11580
11581 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11582 {
11583   if(_mesh)
11584     _mesh->decrRef();
11585   if(_own_cell)
11586     delete _cell;
11587 }
11588
11589 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11590     _own_cell(false),_cell_id(bg-1),
11591     _nb_cell(end)
11592 {
11593   if(mesh)
11594     mesh->incrRef();
11595 }
11596
11597 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11598 {
11599   _cell_id++;
11600   if(_cell_id<_nb_cell)
11601     {
11602       _cell->next();
11603       return _cell;
11604     }
11605   else
11606     return 0;
11607 }
11608
11609 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11610 {
11611   if(_mesh)
11612     _mesh->incrRef();
11613 }
11614
11615 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11616 {
11617   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11618 }
11619
11620 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11621 {
11622   if(_mesh)
11623     _mesh->decrRef();
11624 }
11625
11626 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11627     _itc(itc),
11628     _bg(bg),_end(end)
11629 {
11630   if(_mesh)
11631     _mesh->incrRef();
11632 }
11633
11634 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11635 {
11636   if(_mesh)
11637     _mesh->decrRef();
11638 }
11639
11640 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11641 {
11642   return _type;
11643 }
11644
11645 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11646 {
11647   return _end-_bg;
11648 }
11649
11650 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11651 {
11652   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11653 }
11654
11655 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11656 {
11657   if(mesh)
11658     {
11659       mesh->incrRef();
11660       _nb_cell=mesh->getNumberOfCells();
11661     }
11662 }
11663
11664 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11665 {
11666   if(_mesh)
11667     _mesh->decrRef();
11668   delete _cell;
11669 }
11670
11671 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11672 {
11673   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11674   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11675   if(_cell_id<_nb_cell)
11676     {
11677       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11678       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11679       int startId=_cell_id;
11680       _cell_id+=nbOfElems;
11681       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11682     }
11683   else
11684     return 0;
11685 }
11686
11687 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11688 {
11689   if(mesh)
11690     {
11691       _conn=mesh->getNodalConnectivity()->getPointer();
11692       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11693     }
11694 }
11695
11696 void MEDCouplingUMeshCell::next()
11697 {
11698   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11699     {
11700       _conn+=_conn_lgth;
11701       _conn_indx++;
11702     }
11703   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11704 }
11705
11706 std::string MEDCouplingUMeshCell::repr() const
11707 {
11708   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11709     {
11710       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11711       oss << " : ";
11712       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11713       return oss.str();
11714     }
11715   else
11716     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11717 }
11718
11719 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11720 {
11721   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11722     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11723   else
11724     return INTERP_KERNEL::NORM_ERROR;
11725 }
11726
11727 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11728 {
11729   lgth=_conn_lgth;
11730   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11731     return _conn;
11732   else
11733     return 0;
11734 }