Salome HOME
Fix for duplicateNodesOnM1Group() so that non connex cracking
[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 "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44
45 #include <sstream>
46 #include <fstream>
47 #include <numeric>
48 #include <cstring>
49 #include <limits>
50 #include <list>
51
52 using namespace ParaMEDMEM;
53
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55
56 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 };
57
58 MEDCouplingUMesh *MEDCouplingUMesh::New()
59 {
60   return new MEDCouplingUMesh;
61 }
62
63 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
64 {
65   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
66   ret->setName(meshName);
67   ret->setMeshDimension(meshDim);
68   return ret;
69 }
70
71 /*!
72  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
73  * between \a this and the new mesh.
74  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
75  *          delete this mesh using decrRef() as it is no more needed. 
76  */
77 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
78 {
79   return clone(true);
80 }
81
82 /*!
83  * Returns a new MEDCouplingMesh which is a copy of \a this one.
84  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
85  * this mesh are shared by the new mesh.
86  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
87  *          delete this mesh using decrRef() as it is no more needed. 
88  */
89 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
90 {
91   return new MEDCouplingUMesh(*this,recDeepCpy);
92 }
93
94 /*!
95  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
96  * The coordinates are shared between \a this and the returned instance.
97  * 
98  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
99  * \sa MEDCouplingUMesh::deepCpy
100  */
101 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
102 {
103   checkConnectivityFullyDefined();
104   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
106   ret->setConnectivity(c,ci);
107   return ret.retn();
108 }
109
110 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 {
112   if(!other)
113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
114   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
115   if(!otherC)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
117   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
118   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 }
120
121 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
122 {
123   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
124   return ret;
125 }
126
127 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
128 {
129   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
130   ret.push_back(_nodal_connec);
131   ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
247         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
248           {
249             std::ostringstream oss;
250             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
251             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
252             throw INTERP_KERNEL::Exception(oss.str().c_str());
253           }
254       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
255         {
256           int nodeId=*w;
257           if(nodeId>=0)
258             {
259               if(nodeId>=nbOfNodes)
260                 {
261                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
262                   throw INTERP_KERNEL::Exception(oss.str().c_str());
263                 }
264             }
265           else if(nodeId<-1)
266             {
267               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
268               throw INTERP_KERNEL::Exception(oss.str().c_str());
269             }
270           else
271             {
272               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
273                 {
274                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
275                   throw INTERP_KERNEL::Exception(oss.str().c_str());
276                 }
277             }
278         }
279     }
280 }
281
282
283 /*!
284  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
285  * then \a this mesh is most probably is writable, exchangeable and available for all
286  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
287  *  \param [in] eps - a not used parameter.
288  *  \throw If the mesh dimension is not set.
289  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
290  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
291  *  \throw If the connectivity data array has more than one component.
292  *  \throw If the connectivity data array has a named component.
293  *  \throw If the connectivity index data array has more than one component.
294  *  \throw If the connectivity index data array has a named component.
295  *  \throw If number of nodes defining an element does not correspond to the type of element.
296  *  \throw If the nodal connectivity includes an invalid node id.
297  */
298 void MEDCouplingUMesh::checkCoherency2(double eps) const
299 {
300   checkCoherency1(eps);
301 }
302
303 /*!
304  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
305  * elements contained in the mesh. For more info on the mesh dimension see
306  * \ref MEDCouplingUMeshPage.
307  *  \param [in] meshDim - a new mesh dimension.
308  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
309  */
310 void MEDCouplingUMesh::setMeshDimension(int meshDim)
311 {
312   if(meshDim<-1 || meshDim>3)
313     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
314   _mesh_dim=meshDim;
315   declareAsNew();
316 }
317
318 /*!
319  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
320  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
321  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
322  *
323  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
324  *
325  *  \if ENABLE_EXAMPLES
326  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
328  *  \endif
329  */
330 void MEDCouplingUMesh::allocateCells(int nbOfCells)
331 {
332   if(nbOfCells<0)
333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
334   if(_nodal_connec_index)
335     {
336       _nodal_connec_index->decrRef();
337     }
338   if(_nodal_connec)
339     {
340       _nodal_connec->decrRef();
341     }
342   _nodal_connec_index=DataArrayInt::New();
343   _nodal_connec_index->reserve(nbOfCells+1);
344   _nodal_connec_index->pushBackSilent(0);
345   _nodal_connec=DataArrayInt::New();
346   _nodal_connec->reserve(2*nbOfCells);
347   _types.clear();
348   declareAsNew();
349 }
350
351 /*!
352  * Appends a cell to the connectivity array. For deeper understanding what is
353  * happening see \ref MEDCouplingUMeshNodalConnectivity.
354  *  \param [in] type - type of cell to add.
355  *  \param [in] size - number of nodes constituting this cell.
356  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
357  * 
358  *  \if ENABLE_EXAMPLES
359  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
360  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
361  *  \endif
362  */
363 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
364 {
365   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
366   if(_nodal_connec_index==0)
367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
368   if((int)cm.getDimension()==_mesh_dim)
369     {
370       if(!cm.isDynamic())
371         if(size!=(int)cm.getNumberOfNodes())
372           {
373             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
374             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
375             throw INTERP_KERNEL::Exception(oss.str().c_str());
376           }
377       int idx=_nodal_connec_index->back();
378       int val=idx+size+1;
379       _nodal_connec_index->pushBackSilent(val);
380       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
381       _types.insert(type);
382     }
383   else
384     {
385       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
386       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
387       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
388       throw INTERP_KERNEL::Exception(oss.str().c_str());
389     }
390 }
391
392 /*!
393  * Compacts data arrays to release unused memory. This method is to be called after
394  * finishing cell insertion using \a this->insertNextCell().
395  * 
396  *  \if ENABLE_EXAMPLES
397  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
398  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
399  *  \endif
400  */
401 void MEDCouplingUMesh::finishInsertingCells()
402 {
403   _nodal_connec->pack();
404   _nodal_connec_index->pack();
405   _nodal_connec->declareAsNew();
406   _nodal_connec_index->declareAsNew();
407   updateTime();
408 }
409
410 /*!
411  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
412  * Useful for python users.
413  */
414 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
415 {
416   return new MEDCouplingUMeshCellIterator(this);
417 }
418
419 /*!
420  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
421  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
422  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
423  * Useful for python users.
424  */
425 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
426 {
427   if(!checkConsecutiveCellTypes())
428     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
429   return new MEDCouplingUMeshCellByTypeEntry(this);
430 }
431
432 /*!
433  * Returns a set of all cell types available in \a this mesh.
434  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
435  * \warning this method does not throw any exception even if \a this is not defined.
436  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
437  */
438 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
439 {
440   return _types;
441 }
442
443 /*!
444  * This method returns the sorted list of geometric types in \a this.
445  * 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
446  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
447  *
448  * \throw if connectivity in \a this is not correctly defined.
449  *  
450  * \sa MEDCouplingMesh::getAllGeoTypes
451  */
452 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
453 {
454   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
455   checkConnectivityFullyDefined();
456   int nbOfCells(getNumberOfCells());
457   if(nbOfCells==0)
458     return ret;
459   if(getMeshLength()<1)
460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
461   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
462   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
463   for(int i=1;i<nbOfCells;i++,ci++)
464     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
465       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
466   return ret;
467 }
468
469 /*!
470  * This method is a method that compares \a this and \a other.
471  * This method compares \b all attributes, even names and component names.
472  */
473 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
474 {
475   if(!other)
476     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
477   std::ostringstream oss; oss.precision(15);
478   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
479   if(!otherC)
480     {
481       reason="mesh given in input is not castable in MEDCouplingUMesh !";
482       return false;
483     }
484   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
485     return false;
486   if(_mesh_dim!=otherC->_mesh_dim)
487     {
488       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
489       reason=oss.str();
490       return false;
491     }
492   if(_types!=otherC->_types)
493     {
494       oss << "umesh geometric type mismatch :\nThis geometric types are :";
495       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
496         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
497       oss << "\nOther geometric types are :";
498       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
499         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
500       reason=oss.str();
501       return false;
502     }
503   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
504     if(_nodal_connec==0 || otherC->_nodal_connec==0)
505       {
506         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
507         return false;
508       }
509   if(_nodal_connec!=otherC->_nodal_connec)
510     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
511       {
512         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
513         return false;
514       }
515   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
516     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
517       {
518         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
519         return false;
520       }
521   if(_nodal_connec_index!=otherC->_nodal_connec_index)
522     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
523       {
524         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
525         return false;
526       }
527   return true;
528 }
529
530 /*!
531  * Checks if data arrays of this mesh (node coordinates, nodal
532  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
533  * not considered.
534  *  \param [in] other - the mesh to compare with.
535  *  \param [in] prec - precision value used to compare node coordinates.
536  *  \return bool - \a true if the two meshes are same.
537  */
538 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
539 {
540   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
541   if(!otherC)
542     return false;
543   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
544     return false;
545   if(_mesh_dim!=otherC->_mesh_dim)
546     return false;
547   if(_types!=otherC->_types)
548     return false;
549   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
550     if(_nodal_connec==0 || otherC->_nodal_connec==0)
551       return false;
552   if(_nodal_connec!=otherC->_nodal_connec)
553     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
554       return false;
555   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
556     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
557       return false;
558   if(_nodal_connec_index!=otherC->_nodal_connec_index)
559     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
560       return false;
561   return true;
562 }
563
564 /*!
565  * Checks if \a this and \a other meshes are geometrically equivalent with high
566  * probability, else an exception is thrown. The meshes are considered equivalent if
567  * (1) meshes contain the same number of nodes and the same number of elements of the
568  * same types (2) three cells of the two meshes (first, last and middle) are based
569  * on coincident nodes (with a specified precision).
570  *  \param [in] other - the mesh to compare with.
571  *  \param [in] prec - the precision used to compare nodes of the two meshes.
572  *  \throw If the two meshes do not match.
573  */
574 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
575 {
576   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
577   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
578   if(!otherC)
579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
580 }
581
582 /*!
583  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
584  * cells each node belongs to.
585  * \warning For speed reasons, this method does not check if node ids in the nodal
586  *          connectivity correspond to the size of node coordinates array.
587  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
588  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
589  *        dividing cell ids in \a revNodal into groups each referring to one
590  *        node. Its every element (except the last one) is an index pointing to the
591  *         first id of a group of cells. For example cells sharing the node #1 are 
592  *        described by following range of indices: 
593  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
594  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
595  *        Number of cells sharing the *i*-th node is
596  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
597  * \throw If the coordinates array is not set.
598  * \throw If the nodal connectivity of cells is not defined.
599  * 
600  * \if ENABLE_EXAMPLES
601  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
602  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
603  * \endif
604  */
605 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
606 {
607   checkFullyDefined();
608   int nbOfNodes=getNumberOfNodes();
609   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
610   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
611   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
612   const int *conn=_nodal_connec->getConstPointer();
613   const int *connIndex=_nodal_connec_index->getConstPointer();
614   int nbOfCells=getNumberOfCells();
615   int nbOfEltsInRevNodal=0;
616   for(int eltId=0;eltId<nbOfCells;eltId++)
617     {
618       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
619       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
620       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
621         if(*iter>=0)//for polyhedrons
622           {
623             nbOfEltsInRevNodal++;
624             revNodalIndxPtr[(*iter)+1]++;
625           }
626     }
627   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
628   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
629   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
630   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
631   for(int eltId=0;eltId<nbOfCells;eltId++)
632     {
633       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
634       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
635       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
636         if(*iter>=0)//for polyhedrons
637           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
638     }
639 }
640
641 /// @cond INTERNAL
642
643 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
644 {
645   return id;
646 }
647
648 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
649 {
650   if(!compute)
651     return id+1;
652   else
653     {
654       if(cm.getOrientationStatus(nb,conn1,conn2))
655         return id+1;
656       else
657         return -(id+1);
658     }
659 }
660
661 class MinusOneSonsGenerator
662 {
663 public:
664   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
665   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
666   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
667   static const int DELTA=1;
668 private:
669   const INTERP_KERNEL::CellModel& _cm;
670 };
671
672 class MinusOneSonsGeneratorBiQuadratic
673 {
674 public:
675   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
676   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
677   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
678   static const int DELTA=1;
679 private:
680   const INTERP_KERNEL::CellModel& _cm;
681 };
682
683 class MinusTwoSonsGenerator
684 {
685 public:
686   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
688   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689   static const int DELTA=2;
690 private:
691   const INTERP_KERNEL::CellModel& _cm;
692 };
693
694 /// @endcond
695
696 /*!
697  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
698  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
699  * describing correspondence between cells of \a this and the result meshes are
700  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
701  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
702  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
703  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
704  * \warning For speed reasons, this method does not check if node ids in the nodal
705  *          connectivity correspond to the size of node coordinates array.
706  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
707  *          to write this mesh to the MED file, its cells must be sorted using
708  *          sortCellsInMEDFileFrmt().
709  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
710  *         each cell of \a this mesh.
711  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
712  *        dividing cell ids in \a desc into groups each referring to one
713  *        cell of \a this mesh. Its every element (except the last one) is an index
714  *        pointing to the first id of a group of cells. For example cells of the
715  *        result mesh bounding the cell #1 of \a this mesh are described by following
716  *        range of indices:
717  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
718  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
719  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
720  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
721  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
722  *         by each cell of the result mesh.
723  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
724  *        in the result mesh,
725  *        dividing cell ids in \a revDesc into groups each referring to one
726  *        cell of the result mesh the same way as \a descIndx divides \a desc.
727  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
728  *        delete this mesh using decrRef() as it is no more needed.
729  *  \throw If the coordinates array is not set.
730  *  \throw If the nodal connectivity of cells is node defined.
731  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
732  *         revDescIndx == NULL.
733  * 
734  *  \if ENABLE_EXAMPLES
735  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
736  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
737  *  \endif
738  * \sa buildDescendingConnectivity2()
739  */
740 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
741 {
742   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
743 }
744
745 /*!
746  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
747  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
748  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
749  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
750  * \sa MEDCouplingUMesh::buildDescendingConnectivity
751  */
752 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
753 {
754   checkFullyDefined();
755   if(getMeshDimension()!=3)
756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
757   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
758 }
759
760 /*!
761  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
762  * this->getMeshDimension(), that bound cells of \a this mesh. In
763  * addition arrays describing correspondence between cells of \a this and the result
764  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
765  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
766  *  mesh. This method differs from buildDescendingConnectivity() in that apart
767  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
768  * result meshes. So a positive id means that order of nodes in corresponding cells
769  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
770  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
771  * i.e. cell ids are one-based.
772  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
773  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
774  * \warning For speed reasons, this method does not check if node ids in the nodal
775  *          connectivity correspond to the size of node coordinates array.
776  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
777  *          to write this mesh to the MED file, its cells must be sorted using
778  *          sortCellsInMEDFileFrmt().
779  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
780  *         each cell of \a this mesh.
781  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
782  *        dividing cell ids in \a desc into groups each referring to one
783  *        cell of \a this mesh. Its every element (except the last one) is an index
784  *        pointing to the first id of a group of cells. For example cells of the
785  *        result mesh bounding the cell #1 of \a this mesh are described by following
786  *        range of indices:
787  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
788  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
789  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
790  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
791  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
792  *         by each cell of the result mesh.
793  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
794  *        in the result mesh,
795  *        dividing cell ids in \a revDesc into groups each referring to one
796  *        cell of the result mesh the same way as \a descIndx divides \a desc.
797  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
798  *        shares the node coordinates array with \a this mesh. The caller is to
799  *        delete this mesh using decrRef() as it is no more needed.
800  *  \throw If the coordinates array is not set.
801  *  \throw If the nodal connectivity of cells is node defined.
802  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
803  *         revDescIndx == NULL.
804  * 
805  *  \if ENABLE_EXAMPLES
806  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
807  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
808  *  \endif
809  * \sa buildDescendingConnectivity()
810  */
811 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
812 {
813   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
814 }
815
816 /*!
817  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
819  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
820  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
821  *
822  * \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
823  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
824  * \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.
825  */
826 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
827 {
828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
832   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
833   meshDM1=0;
834   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
835 }
836
837 /*!
838  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
839  * 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,
840  * excluding a set of meshdim-1 cells in input descending connectivity.
841  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
842  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
843  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
844  *
845  * \param [in] desc descending connectivity array.
846  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
847  * \param [in] revDesc reverse descending connectivity array.
848  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
849  * \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
850  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
851  * \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.
852  */
853 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
854                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
855 {
856   if(!desc || !descIndx || !revDesc || !revDescIndx)
857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
858   const int *descPtr=desc->getConstPointer();
859   const int *descIPtr=descIndx->getConstPointer();
860   const int *revDescPtr=revDesc->getConstPointer();
861   const int *revDescIPtr=revDescIndx->getConstPointer();
862   //
863   int nbCells=descIndx->getNumberOfTuples()-1;
864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
866   int *out1Ptr=out1->getPointer();
867   *out1Ptr++=0;
868   out0->reserve(desc->getNumberOfTuples());
869   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
870     {
871       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
872         {
873           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
874           s.erase(i);
875           out0->insertAtTheEnd(s.begin(),s.end());
876         }
877       *out1Ptr=out0->getNumberOfTuples();
878     }
879   neighbors=out0.retn();
880   neighborsIndx=out1.retn();
881 }
882
883 /*!
884  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
885  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
886  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
887  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
888  *
889  * \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
890  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
891  * \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.
892  */
893 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
894 {
895   checkFullyDefined();
896   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
898   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
899   switch(mdim)
900   {
901     case 3:
902       {
903         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
904         break;
905       }
906     case 2:
907       {
908         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
909         break;
910       }
911     case 1:
912       {
913         mesh1D=const_cast<MEDCouplingUMesh *>(this);
914         mesh1D->incrRef();
915         break;
916       }
917     default:
918       {
919         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
920       }
921   }
922   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
923   mesh1D->getReverseNodalConnectivity(desc,descIndx);
924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
925   ret0->alloc(desc->getNumberOfTuples(),1);
926   int *r0Pt(ret0->getPointer());
927   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
928   for(int i=0;i<nbNodes;i++,rni++)
929     {
930       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
931         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
932     }
933   neighbors=ret0.retn();
934   neighborsIdx=descIndx.retn();
935 }
936
937 /// @cond INTERNAL
938
939 /*!
940  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
941  * For speed reasons no check of this will be done.
942  */
943 template<class SonsGenerator>
944 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
945 {
946   if(!desc || !descIndx || !revDesc || !revDescIndx)
947     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
948   checkConnectivityFullyDefined();
949   int nbOfCells=getNumberOfCells();
950   int nbOfNodes=getNumberOfNodes();
951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
952   int *revNodalIndxPtr=revNodalIndx->getPointer();
953   const int *conn=_nodal_connec->getConstPointer();
954   const int *connIndex=_nodal_connec_index->getConstPointer();
955   std::string name="Mesh constituent of "; name+=getName();
956   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
957   ret->setCoords(getCoords());
958   ret->allocateCells(2*nbOfCells);
959   descIndx->alloc(nbOfCells+1,1);
960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
961   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
962   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
963     {
964       int pos=connIndex[eltId];
965       int posP1=connIndex[eltId+1];
966       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
967       SonsGenerator sg(cm);
968       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
969       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
970       for(unsigned i=0;i<nbOfSons;i++)
971         {
972           INTERP_KERNEL::NormalizedCellType cmsId;
973           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
974           for(unsigned k=0;k<nbOfNodesSon;k++)
975             if(tmp[k]>=0)
976               revNodalIndxPtr[tmp[k]+1]++;
977           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
978           revDesc2->pushBackSilent(eltId);
979         }
980       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
981     }
982   int nbOfCellsM1=ret->getNumberOfCells();
983   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
985   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
986   int *revNodalPtr=revNodal->getPointer();
987   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
988   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
989   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
990     {
991       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
992       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
993       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
994         if(*iter>=0)//for polyhedrons
995           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
996     }
997   //
998   DataArrayInt *commonCells=0,*commonCellsI=0;
999   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1001   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1002   int newNbOfCellsM1=-1;
1003   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1004                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1005   std::vector<bool> isImpacted(nbOfCellsM1,false);
1006   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1007     for(int work2=work[0];work2!=work[1];work2++)
1008       isImpacted[commonCellsPtr[work2]]=true;
1009   const int *o2nM1Ptr=o2nM1->getConstPointer();
1010   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1011   const int *n2oM1Ptr=n2oM1->getConstPointer();
1012   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1013   ret2->copyTinyInfoFrom(this);
1014   desc->alloc(descIndx->back(),1);
1015   int *descPtr=desc->getPointer();
1016   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1017   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1018     {
1019       if(!isImpacted[i])
1020         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1021       else
1022         {
1023           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1024             {
1025               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1026               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1027             }
1028           else
1029             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1030         }
1031     }
1032   revDesc->reserve(newNbOfCellsM1);
1033   revDescIndx->alloc(newNbOfCellsM1+1,1);
1034   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1035   const int *revDesc2Ptr=revDesc2->getConstPointer();
1036   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1037     {
1038       int oldCellIdM1=n2oM1Ptr[i];
1039       if(!isImpacted[oldCellIdM1])
1040         {
1041           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1042           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1043         }
1044       else
1045         {
1046           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1047             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1048           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1049           commonCellsIPtr++;
1050         }
1051     }
1052   //
1053   return ret2.retn();
1054 }
1055
1056 struct MEDCouplingAccVisit
1057 {
1058   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1059   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1060   int _new_nb_of_nodes;
1061 };
1062
1063 /// @endcond
1064
1065 /*!
1066  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1067  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1068  * array of cell ids. Pay attention that after conversion all algorithms work slower
1069  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1070  * conversion due presence of invalid ids in the array of cells to convert, as a
1071  * result \a this mesh contains some already converted elements. In this case the 2D
1072  * mesh remains valid but 3D mesh becomes \b inconsistent!
1073  *  \warning This method can significantly modify the order of geometric types in \a this,
1074  *          hence, to write this mesh to the MED file, its cells must be sorted using
1075  *          sortCellsInMEDFileFrmt().
1076  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1077  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1078  *         cellIdsToConvertBg.
1079  *  \throw If the coordinates array is not set.
1080  *  \throw If the nodal connectivity of cells is node defined.
1081  *  \throw If dimension of \a this mesh is not either 2 or 3.
1082  *
1083  *  \if ENABLE_EXAMPLES
1084  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1085  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1086  *  \endif
1087  */
1088 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1089 {
1090   checkFullyDefined();
1091   int dim=getMeshDimension();
1092   if(dim<2 || dim>3)
1093     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1094   int nbOfCells(getNumberOfCells());
1095   if(dim==2)
1096     {
1097       const int *connIndex=_nodal_connec_index->getConstPointer();
1098       int *conn=_nodal_connec->getPointer();
1099       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1100         {
1101           if(*iter>=0 && *iter<nbOfCells)
1102             {
1103               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1104               if(!cm.isQuadratic())
1105                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1106               else
1107                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1108             }
1109           else
1110             {
1111               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1112               oss << " in range [0," << nbOfCells << ") !";
1113               throw INTERP_KERNEL::Exception(oss.str().c_str());
1114             }
1115         }
1116     }
1117   else
1118     {
1119       int *connIndex(_nodal_connec_index->getPointer());
1120       const int *connOld(_nodal_connec->getConstPointer());
1121       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1122       std::vector<bool> toBeDone(nbOfCells,false);
1123       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1124         {
1125           if(*iter>=0 && *iter<nbOfCells)
1126             toBeDone[*iter]=true;
1127           else
1128             {
1129               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1130               oss << " in range [0," << nbOfCells << ") !";
1131               throw INTERP_KERNEL::Exception(oss.str().c_str());
1132             }
1133         }
1134       for(int cellId=0;cellId<nbOfCells;cellId++)
1135         {
1136           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1137           int lgthOld(posP1-pos-1);
1138           if(toBeDone[cellId])
1139             {
1140               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1141               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1142               int *tmp(new int[nbOfFaces*lgthOld+1]);
1143               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1144               for(unsigned j=0;j<nbOfFaces;j++)
1145                 {
1146                   INTERP_KERNEL::NormalizedCellType type;
1147                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1148                   work+=offset;
1149                   *work++=-1;
1150                 }
1151               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1152               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1153               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1154               delete [] tmp;
1155             }
1156           else
1157             {
1158               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1159               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1160             }
1161         }
1162       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1163     }
1164   computeTypes();
1165 }
1166
1167 /*!
1168  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1169  * polyhedrons (if \a this is a 3D mesh).
1170  *  \warning As this method is purely for user-friendliness and no optimization is
1171  *          done to avoid construction of a useless vector, this method can be costly
1172  *          in memory.
1173  *  \throw If the coordinates array is not set.
1174  *  \throw If the nodal connectivity of cells is node defined.
1175  *  \throw If dimension of \a this mesh is not either 2 or 3.
1176  */
1177 void MEDCouplingUMesh::convertAllToPoly()
1178 {
1179   int nbOfCells=getNumberOfCells();
1180   std::vector<int> cellIds(nbOfCells);
1181   for(int i=0;i<nbOfCells;i++)
1182     cellIds[i]=i;
1183   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1184 }
1185
1186 /*!
1187  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1188  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1189  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1190  * base facet of the volume and the second half of nodes describes an opposite facet
1191  * having the same number of nodes as the base one. This method converts such
1192  * connectivity to a valid polyhedral format where connectivity of each facet is
1193  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1194  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1195  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1196  * a correct orientation of the first facet of a polyhedron, else orientation of a
1197  * corrected cell is reverse.<br>
1198  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1199  * it releases the user from boring description of polyhedra connectivity in the valid
1200  * format.
1201  *  \throw If \a this->getMeshDimension() != 3.
1202  *  \throw If \a this->getSpaceDimension() != 3.
1203  *  \throw If the nodal connectivity of cells is not defined.
1204  *  \throw If the coordinates array is not set.
1205  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1206  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1207  *
1208  *  \if ENABLE_EXAMPLES
1209  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1210  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1211  *  \endif
1212  */
1213 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1214 {
1215   checkFullyDefined();
1216   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1217     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1218   int nbOfCells=getNumberOfCells();
1219   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1220   newCi->alloc(nbOfCells+1,1);
1221   int *newci=newCi->getPointer();
1222   const int *ci=_nodal_connec_index->getConstPointer();
1223   const int *c=_nodal_connec->getConstPointer();
1224   newci[0]=0;
1225   for(int i=0;i<nbOfCells;i++)
1226     {
1227       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1228       if(type==INTERP_KERNEL::NORM_POLYHED)
1229         {
1230           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1231             {
1232               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1233               throw INTERP_KERNEL::Exception(oss.str().c_str());
1234             }
1235           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1236           if(n2%2!=0)
1237             {
1238               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 !";
1239               throw INTERP_KERNEL::Exception(oss.str().c_str());
1240             }
1241           int n1=(int)(n2/2);
1242           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)
1243         }
1244       else
1245         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1246     }
1247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1248   newC->alloc(newci[nbOfCells],1);
1249   int *newc=newC->getPointer();
1250   for(int i=0;i<nbOfCells;i++)
1251     {
1252       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1253       if(type==INTERP_KERNEL::NORM_POLYHED)
1254         {
1255           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1256           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1257           *newc++=-1;
1258           for(std::size_t j=0;j<n1;j++)
1259             {
1260               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1261               newc[n1+5*j]=-1;
1262               newc[n1+5*j+1]=c[ci[i]+1+j];
1263               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1264               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1265               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1266             }
1267           newc+=n1*6;
1268         }
1269       else
1270         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1271     }
1272   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1273   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1274 }
1275
1276
1277 /*!
1278  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1279  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1280  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1281  *          to write this mesh to the MED file, its cells must be sorted using
1282  *          sortCellsInMEDFileFrmt().
1283  * \return \c true if at least one cell has been converted, \c false else. In the
1284  *         last case the nodal connectivity remains unchanged.
1285  * \throw If the coordinates array is not set.
1286  * \throw If the nodal connectivity of cells is not defined.
1287  * \throw If \a this->getMeshDimension() < 0.
1288  */
1289 bool MEDCouplingUMesh::unPolyze()
1290 {
1291   checkFullyDefined();
1292   int mdim=getMeshDimension();
1293   if(mdim<0)
1294     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1295   if(mdim<=1)
1296     return false;
1297   int nbOfCells=getNumberOfCells();
1298   if(nbOfCells<1)
1299     return false;
1300   int initMeshLgth=getMeshLength();
1301   int *conn=_nodal_connec->getPointer();
1302   int *index=_nodal_connec_index->getPointer();
1303   int posOfCurCell=0;
1304   int newPos=0;
1305   int lgthOfCurCell;
1306   bool ret=false;
1307   for(int i=0;i<nbOfCells;i++)
1308     {
1309       lgthOfCurCell=index[i+1]-posOfCurCell;
1310       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1311       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1312       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1313       int newLgth;
1314       if(cm.isDynamic())
1315         {
1316           switch(cm.getDimension())
1317           {
1318             case 2:
1319               {
1320                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1321                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1322                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1323                 break;
1324               }
1325             case 3:
1326               {
1327                 int nbOfFaces,lgthOfPolyhConn;
1328                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1329                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1330                 break;
1331               }
1332             case 1:
1333               {
1334                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1335                 break;
1336               }
1337           }
1338           ret=ret || (newType!=type);
1339           conn[newPos]=newType;
1340           newPos+=newLgth+1;
1341           posOfCurCell=index[i+1];
1342           index[i+1]=newPos;
1343         }
1344       else
1345         {
1346           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1347           newPos+=lgthOfCurCell;
1348           posOfCurCell+=lgthOfCurCell;
1349           index[i+1]=newPos;
1350         }
1351     }
1352   if(newPos!=initMeshLgth)
1353     _nodal_connec->reAlloc(newPos);
1354   if(ret)
1355     computeTypes();
1356   return ret;
1357 }
1358
1359 /*!
1360  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1361  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1362  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1363  *
1364  * \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 
1365  *             precision.
1366  */
1367 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1368 {
1369   checkFullyDefined();
1370   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1372   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1373   coords->recenterForMaxPrecision(eps);
1374   //
1375   int nbOfCells=getNumberOfCells();
1376   const int *conn=_nodal_connec->getConstPointer();
1377   const int *index=_nodal_connec_index->getConstPointer();
1378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1379   connINew->alloc(nbOfCells+1,1);
1380   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1382   bool changed=false;
1383   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1384     {
1385       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1386         {
1387           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1388           changed=true;
1389         }
1390       else
1391         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1392       *connINewPtr=connNew->getNumberOfTuples();
1393     }
1394   if(changed)
1395     setConnectivity(connNew,connINew,false);
1396 }
1397
1398 /*!
1399  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1400  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1401  * the format of the returned DataArrayInt instance.
1402  * 
1403  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1404  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1405  */
1406 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1407 {
1408   checkConnectivityFullyDefined();
1409   int nbOfCells=getNumberOfCells();
1410   const int *connIndex=_nodal_connec_index->getConstPointer();
1411   const int *conn=_nodal_connec->getConstPointer();
1412   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1413   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1414   std::vector<bool> retS(maxElt,false);
1415   for(int i=0;i<nbOfCells;i++)
1416     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1417       if(conn[j]>=0)
1418         retS[conn[j]]=true;
1419   int sz=0;
1420   for(int i=0;i<maxElt;i++)
1421     if(retS[i])
1422       sz++;
1423   DataArrayInt *ret=DataArrayInt::New();
1424   ret->alloc(sz,1);
1425   int *retPtr=ret->getPointer();
1426   for(int i=0;i<maxElt;i++)
1427     if(retS[i])
1428       *retPtr++=i;
1429   return ret;
1430 }
1431
1432 /*!
1433  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1434  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1435  */
1436 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1437 {
1438   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1439   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1440   for(int i=0;i<nbOfCells;i++)
1441     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1442       if(conn[j]>=0)
1443         {
1444           if(conn[j]<nbOfNodes)
1445             nodeIdsInUse[conn[j]]=true;
1446           else
1447             {
1448               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1449               throw INTERP_KERNEL::Exception(oss.str().c_str());
1450             }
1451         }
1452 }
1453
1454 /*!
1455  * Finds nodes not used in any cell and returns an array giving a new id to every node
1456  * by excluding the unused nodes, for which the array holds -1. The result array is
1457  * a mapping in "Old to New" mode. 
1458  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1459  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1460  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1461  *          if the node is unused or a new id else. The caller is to delete this
1462  *          array using decrRef() as it is no more needed.  
1463  *  \throw If the coordinates array is not set.
1464  *  \throw If the nodal connectivity of cells is not defined.
1465  *  \throw If the nodal connectivity includes an invalid id.
1466  *
1467  *  \if ENABLE_EXAMPLES
1468  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1469  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1470  *  \endif
1471  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1472  */
1473 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1474 {
1475   nbrOfNodesInUse=-1;
1476   int nbOfNodes(getNumberOfNodes());
1477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1478   ret->alloc(nbOfNodes,1);
1479   int *traducer=ret->getPointer();
1480   std::fill(traducer,traducer+nbOfNodes,-1);
1481   int nbOfCells=getNumberOfCells();
1482   const int *connIndex=_nodal_connec_index->getConstPointer();
1483   const int *conn=_nodal_connec->getConstPointer();
1484   for(int i=0;i<nbOfCells;i++)
1485     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1486       if(conn[j]>=0)
1487         {
1488           if(conn[j]<nbOfNodes)
1489             traducer[conn[j]]=1;
1490           else
1491             {
1492               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1493               throw INTERP_KERNEL::Exception(oss.str().c_str());
1494             }
1495         }
1496   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1497   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1498   return ret.retn();
1499 }
1500
1501 /*!
1502  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1503  * For each cell in \b this the number of nodes constituting cell is computed.
1504  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1505  * So for pohyhedrons some nodes can be counted several times in the returned result.
1506  * 
1507  * \return a newly allocated array
1508  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1509  */
1510 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1511 {
1512   checkConnectivityFullyDefined();
1513   int nbOfCells=getNumberOfCells();
1514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1515   ret->alloc(nbOfCells,1);
1516   int *retPtr=ret->getPointer();
1517   const int *conn=getNodalConnectivity()->getConstPointer();
1518   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1519   for(int i=0;i<nbOfCells;i++,retPtr++)
1520     {
1521       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1522         *retPtr=connI[i+1]-connI[i]-1;
1523       else
1524         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1525     }
1526   return ret.retn();
1527 }
1528
1529 /*!
1530  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1531  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1532  *
1533  * \return DataArrayInt * - new object to be deallocated by the caller.
1534  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1535  */
1536 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1537 {
1538   checkConnectivityFullyDefined();
1539   int nbOfCells=getNumberOfCells();
1540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1541   ret->alloc(nbOfCells,1);
1542   int *retPtr=ret->getPointer();
1543   const int *conn=getNodalConnectivity()->getConstPointer();
1544   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1545   for(int i=0;i<nbOfCells;i++,retPtr++)
1546     {
1547       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1548       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1549         *retPtr=(int)s.size();
1550       else
1551         {
1552           s.erase(-1);
1553           *retPtr=(int)s.size();
1554         }
1555     }
1556   return ret.retn();
1557 }
1558
1559 /*!
1560  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1561  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1562  * 
1563  * \return a newly allocated array
1564  */
1565 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1566 {
1567   checkConnectivityFullyDefined();
1568   int nbOfCells=getNumberOfCells();
1569   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1570   ret->alloc(nbOfCells,1);
1571   int *retPtr=ret->getPointer();
1572   const int *conn=getNodalConnectivity()->getConstPointer();
1573   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1574   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1575     {
1576       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1577       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1578     }
1579   return ret.retn();
1580 }
1581
1582 /*!
1583  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1584  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1585  * array mean that the corresponding old node is no more used. 
1586  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1587  *           this->getNumberOfNodes() before call of this method. The caller is to
1588  *           delete this array using decrRef() as it is no more needed. 
1589  *  \throw If the coordinates array is not set.
1590  *  \throw If the nodal connectivity of cells is not defined.
1591  *  \throw If the nodal connectivity includes an invalid id.
1592  *  \sa areAllNodesFetched
1593  *
1594  *  \if ENABLE_EXAMPLES
1595  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1596  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1597  *  \endif
1598  */
1599 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1600 {
1601   return MEDCouplingPointSet::zipCoordsTraducer();
1602 }
1603
1604 /*!
1605  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1606  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1607  */
1608 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1609 {
1610   switch(compType)
1611   {
1612     case 0:
1613       return AreCellsEqual0(conn,connI,cell1,cell2);
1614     case 1:
1615       return AreCellsEqual1(conn,connI,cell1,cell2);
1616     case 2:
1617       return AreCellsEqual2(conn,connI,cell1,cell2);
1618     case 3:
1619       return AreCellsEqual3(conn,connI,cell1,cell2);
1620     case 7:
1621       return AreCellsEqual7(conn,connI,cell1,cell2);
1622   }
1623   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1624 }
1625
1626 /*!
1627  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1628  */
1629 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1630 {
1631   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1632     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1633   return 0;
1634 }
1635
1636 /*!
1637  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1638  */
1639 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1640 {
1641   int sz=connI[cell1+1]-connI[cell1];
1642   if(sz==connI[cell2+1]-connI[cell2])
1643     {
1644       if(conn[connI[cell1]]==conn[connI[cell2]])
1645         {
1646           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1647           unsigned dim=cm.getDimension();
1648           if(dim!=3)
1649             {
1650               if(dim!=1)
1651                 {
1652                   int sz1=2*(sz-1);
1653                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1654                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1655                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1656                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1657                   return work!=tmp+sz1?1:0;
1658                 }
1659               else
1660                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1661             }
1662           else
1663             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1664         }
1665     }
1666   return 0;
1667 }
1668
1669 /*!
1670  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1671  */
1672 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1673 {
1674   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1675     {
1676       if(conn[connI[cell1]]==conn[connI[cell2]])
1677         {
1678           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1679           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1680           return s1==s2?1:0;
1681         }
1682     }
1683   return 0;
1684 }
1685
1686 /*!
1687  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1688  */
1689 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1690 {
1691   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1692     {
1693       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1694       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1695       return s1==s2?1:0;
1696     }
1697   return 0;
1698 }
1699
1700 /*!
1701  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1702  */
1703 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1704 {
1705   int sz=connI[cell1+1]-connI[cell1];
1706   if(sz==connI[cell2+1]-connI[cell2])
1707     {
1708       if(conn[connI[cell1]]==conn[connI[cell2]])
1709         {
1710           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1711           unsigned dim=cm.getDimension();
1712           if(dim!=3)
1713             {
1714               if(dim!=1)
1715                 {
1716                   int sz1=2*(sz-1);
1717                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1718                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1719                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1720                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1721                   if(work!=tmp+sz1)
1722                     return 1;
1723                   else
1724                     {
1725                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1726                       std::reverse_iterator<int *> it2((int *)tmp);
1727                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1728                         return 2;
1729                       else
1730                         return 0;
1731                     }
1732
1733                   return work!=tmp+sz1?1:0;
1734                 }
1735               else
1736                 {//case of SEG2 and SEG3
1737                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1738                     return 1;
1739                   if(!cm.isQuadratic())
1740                     {
1741                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1742                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1743                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1744                         return 2;
1745                       return 0;
1746                     }
1747                   else
1748                     {
1749                       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])
1750                         return 2;
1751                       return 0;
1752                     }
1753                 }
1754             }
1755           else
1756             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1757         }
1758     }
1759   return 0;
1760 }
1761
1762 /*!
1763  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1764  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1765  * and result remains unchanged.
1766  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1767  * If in 'candidates' pool -1 value is considered as an empty value.
1768  * WARNING this method returns only ONE set of result !
1769  */
1770 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1771 {
1772   if(candidates.size()<1)
1773     return false;
1774   bool ret=false;
1775   std::vector<int>::const_iterator iter=candidates.begin();
1776   int start=(*iter++);
1777   for(;iter!=candidates.end();iter++)
1778     {
1779       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1780       if(status!=0)
1781         {
1782           if(!ret)
1783             {
1784               result->pushBackSilent(start);
1785               ret=true;
1786             }
1787           if(status==1)
1788             result->pushBackSilent(*iter);
1789           else
1790             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1791         }
1792     }
1793   return ret;
1794 }
1795
1796 /*!
1797  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1798  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1799  *
1800  * \param [in] compType input specifying the technique used to compare cells each other.
1801  *   - 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.
1802  *   - 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)
1803  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1804  *   - 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
1805  * can be used for users not sensitive to orientation of cell
1806  * \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.
1807  * \param [out] commonCells
1808  * \param [out] commonCellsI
1809  * \return the correspondance array old to new in a newly allocated array.
1810  * 
1811  */
1812 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1813 {
1814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1815   getReverseNodalConnectivity(revNodal,revNodalI);
1816   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1817 }
1818
1819 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1820                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1821 {
1822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1823   int nbOfCells=nodalI->getNumberOfTuples()-1;
1824   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1825   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1826   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1827   std::vector<bool> isFetched(nbOfCells,false);
1828   if(startCellId==0)
1829     {
1830       for(int i=0;i<nbOfCells;i++)
1831         {
1832           if(!isFetched[i])
1833             {
1834               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1835               std::vector<int> v,v2;
1836               if(connOfNode!=connPtr+connIPtr[i+1])
1837                 {
1838                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1839                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1840                   connOfNode++;
1841                 }
1842               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1843                 if(*connOfNode>=0)
1844                   {
1845                     v=v2;
1846                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1847                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1848                     v2.resize(std::distance(v2.begin(),it));
1849                   }
1850               if(v2.size()>1)
1851                 {
1852                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1853                     {
1854                       int pos=commonCellsI->back();
1855                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1856                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1857                         isFetched[*it]=true;
1858                     }
1859                 }
1860             }
1861         }
1862     }
1863   else
1864     {
1865       for(int i=startCellId;i<nbOfCells;i++)
1866         {
1867           if(!isFetched[i])
1868             {
1869               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1870               std::vector<int> v,v2;
1871               if(connOfNode!=connPtr+connIPtr[i+1])
1872                 {
1873                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1874                   connOfNode++;
1875                 }
1876               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1877                 if(*connOfNode>=0)
1878                   {
1879                     v=v2;
1880                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1881                     v2.resize(std::distance(v2.begin(),it));
1882                   }
1883               if(v2.size()>1)
1884                 {
1885                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1886                     {
1887                       int pos=commonCellsI->back();
1888                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1889                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1890                         isFetched[*it]=true;
1891                     }
1892                 }
1893             }
1894         }
1895     }
1896   commonCellsArr=commonCells.retn();
1897   commonCellsIArr=commonCellsI.retn();
1898 }
1899
1900 /*!
1901  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1902  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1903  * than \a other->getNumberOfCells() in the returned array means that there is no
1904  * corresponding cell in \a this mesh.
1905  * It is expected that \a this and \a other meshes share the same node coordinates
1906  * array, if it is not so an exception is thrown. 
1907  *  \param [in] other - the mesh to compare with.
1908  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1909  *         valid values [0,1,2], see zipConnectivityTraducer().
1910  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1911  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1912  *         values. The caller is to delete this array using
1913  *         decrRef() as it is no more needed.
1914  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1915  *         mesh.
1916  *
1917  *  \if ENABLE_EXAMPLES
1918  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1919  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1920  *  \endif
1921  *  \sa checkDeepEquivalOnSameNodesWith()
1922  *  \sa checkGeoEquivalWith()
1923  */
1924 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1925 {
1926   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1927   int nbOfCells=getNumberOfCells();
1928   static const int possibleCompType[]={0,1,2};
1929   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1930     {
1931       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1932       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1933       oss << " !";
1934       throw INTERP_KERNEL::Exception(oss.str().c_str());
1935     }
1936   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1937   arr=o2n->substr(nbOfCells);
1938   arr->setName(other->getName());
1939   int tmp;
1940   if(other->getNumberOfCells()==0)
1941     return true;
1942   return arr->getMaxValue(tmp)<nbOfCells;
1943 }
1944
1945 /*!
1946  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1947  * This method tries to determine if \b other is fully included in \b this.
1948  * The main difference is that this method is not expected to throw exception.
1949  * This method has two outputs :
1950  *
1951  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1952  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1953  */
1954 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1955 {
1956   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1957   DataArrayInt *commonCells=0,*commonCellsI=0;
1958   int thisNbCells=getNumberOfCells();
1959   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1961   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1962   int otherNbCells=other->getNumberOfCells();
1963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1964   arr2->alloc(otherNbCells,1);
1965   arr2->fillWithZero();
1966   int *arr2Ptr=arr2->getPointer();
1967   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1968   for(int i=0;i<nbOfCommon;i++)
1969     {
1970       int start=commonCellsPtr[commonCellsIPtr[i]];
1971       if(start<thisNbCells)
1972         {
1973           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1974             {
1975               int sig=commonCellsPtr[j]>0?1:-1;
1976               int val=std::abs(commonCellsPtr[j])-1;
1977               if(val>=thisNbCells)
1978                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1979             }
1980         }
1981     }
1982   arr2->setName(other->getName());
1983   if(arr2->presenceOfValue(0))
1984     return false;
1985   arr=arr2.retn();
1986   return true;
1987 }
1988
1989 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1990 {
1991   if(!other)
1992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1993   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1994   if(!otherC)
1995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1996   std::vector<const MEDCouplingUMesh *> ms(2);
1997   ms[0]=this;
1998   ms[1]=otherC;
1999   return MergeUMeshesOnSameCoords(ms);
2000 }
2001
2002 /*!
2003  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2004  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2005  * cellIds is not given explicitely but by a range python like.
2006  * 
2007  * \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.
2008  * \return a newly allocated
2009  * 
2010  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2011  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2012  */
2013 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2014 {
2015   if(getMeshDimension()!=-1)
2016     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2017   else
2018     {
2019       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2020       if(newNbOfCells!=1)
2021         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2022       if(start!=0)
2023         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2024       incrRef();
2025       return const_cast<MEDCouplingUMesh *>(this);
2026     }
2027 }
2028
2029 /*!
2030  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2031  * The result mesh shares or not the node coordinates array with \a this mesh depending
2032  * on \a keepCoords parameter.
2033  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2034  *           to write this mesh to the MED file, its cells must be sorted using
2035  *           sortCellsInMEDFileFrmt().
2036  *  \param [in] begin - an array of cell ids to include to the new mesh.
2037  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2038  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2039  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2040  *         by calling zipCoords().
2041  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2042  *         to delete this mesh using decrRef() as it is no more needed. 
2043  *  \throw If the coordinates array is not set.
2044  *  \throw If the nodal connectivity of cells is not defined.
2045  *  \throw If any cell id in the array \a begin is not valid.
2046  *
2047  *  \if ENABLE_EXAMPLES
2048  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2049  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2050  *  \endif
2051  */
2052 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2053 {
2054   if(getMeshDimension()!=-1)
2055     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2056   else
2057     {
2058       if(end-begin!=1)
2059         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2060       if(begin[0]!=0)
2061         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2062       incrRef();
2063       return const_cast<MEDCouplingUMesh *>(this);
2064     }
2065 }
2066
2067 /*!
2068  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2069  *
2070  * 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.
2071  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2072  * The number of cells of \b this will remain the same with this method.
2073  *
2074  * \param [in] begin begin of cell ids (included) of cells in this to assign
2075  * \param [in] end end of cell ids (excluded) of cells in this to assign
2076  * \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 ).
2077  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2078  */
2079 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2080 {
2081   checkConnectivityFullyDefined();
2082   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2083   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2084     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2085   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2086     {
2087       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2088       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2089       throw INTERP_KERNEL::Exception(oss.str().c_str());
2090     }
2091   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2092   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2093     {
2094       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2095       throw INTERP_KERNEL::Exception(oss.str().c_str());
2096     }
2097   int nbOfCells=getNumberOfCells();
2098   bool easyAssign=true;
2099   const int *connI=_nodal_connec_index->getConstPointer();
2100   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2101   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2102     {
2103       if(*it>=0 && *it<nbOfCells)
2104         {
2105           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2106         }
2107       else
2108         {
2109           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2110           throw INTERP_KERNEL::Exception(oss.str().c_str());
2111         }
2112     }
2113   if(easyAssign)
2114     {
2115       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2116       computeTypes();
2117     }
2118   else
2119     {
2120       DataArrayInt *arrOut=0,*arrIOut=0;
2121       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2122                                                arrOut,arrIOut);
2123       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2124       setConnectivity(arrOut,arrIOut,true);
2125     }
2126 }
2127
2128 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2129 {
2130   checkConnectivityFullyDefined();
2131   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2132   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2133     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2134   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2135     {
2136       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2137       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2138       throw INTERP_KERNEL::Exception(oss.str().c_str());
2139     }
2140   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2141   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2142     {
2143       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2144       throw INTERP_KERNEL::Exception(oss.str().c_str());
2145     }
2146   int nbOfCells=getNumberOfCells();
2147   bool easyAssign=true;
2148   const int *connI=_nodal_connec_index->getConstPointer();
2149   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2150   int it=start;
2151   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2152     {
2153       if(it>=0 && it<nbOfCells)
2154         {
2155           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2156         }
2157       else
2158         {
2159           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2160           throw INTERP_KERNEL::Exception(oss.str().c_str());
2161         }
2162     }
2163   if(easyAssign)
2164     {
2165       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2166       computeTypes();
2167     }
2168   else
2169     {
2170       DataArrayInt *arrOut=0,*arrIOut=0;
2171       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2172                                                 arrOut,arrIOut);
2173       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2174       setConnectivity(arrOut,arrIOut,true);
2175     }
2176 }                      
2177
2178 /*!
2179  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2180  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2181  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2182  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2183  *
2184  * \param [in] begin input start of array of node ids.
2185  * \param [in] end input end of array of node ids.
2186  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2187  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2188  */
2189 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2190 {
2191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2192   checkConnectivityFullyDefined();
2193   int tmp=-1;
2194   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2195   std::vector<bool> fastFinder(sz,false);
2196   for(const int *work=begin;work!=end;work++)
2197     if(*work>=0 && *work<sz)
2198       fastFinder[*work]=true;
2199   int nbOfCells=getNumberOfCells();
2200   const int *conn=getNodalConnectivity()->getConstPointer();
2201   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2202   for(int i=0;i<nbOfCells;i++)
2203     {
2204       int ref=0,nbOfHit=0;
2205       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2206         if(*work2>=0)
2207           {
2208             ref++;
2209             if(fastFinder[*work2])
2210               nbOfHit++;
2211           }
2212       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2213         cellIdsKept->pushBackSilent(i);
2214     }
2215   cellIdsKeptArr=cellIdsKept.retn();
2216 }
2217
2218 /*!
2219  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2220  * this->getMeshDimension(), that bound some cells of \a this mesh.
2221  * The cells of lower dimension to include to the result mesh are selected basing on
2222  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2223  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2224  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2225  * created mesh shares the node coordinates array with \a this mesh. 
2226  *  \param [in] begin - the array of node ids.
2227  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2228  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2229  *         array \a begin are added, else cells whose any node is in the
2230  *         array \a begin are added.
2231  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2232  *         to delete this mesh using decrRef() as it is no more needed. 
2233  *  \throw If the coordinates array is not set.
2234  *  \throw If the nodal connectivity of cells is not defined.
2235  *  \throw If any node id in \a begin is not valid.
2236  *
2237  *  \if ENABLE_EXAMPLES
2238  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2239  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2240  *  \endif
2241  */
2242 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2243 {
2244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2245   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2246   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2247   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2248   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2249 }
2250
2251 /*!
2252  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2253  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2254  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2255  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2256  *         by calling zipCoords().
2257  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2258  *         to delete this mesh using decrRef() as it is no more needed. 
2259  *  \throw If the coordinates array is not set.
2260  *  \throw If the nodal connectivity of cells is not defined.
2261  *
2262  *  \if ENABLE_EXAMPLES
2263  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2264  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2265  *  \endif
2266  */
2267 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2268 {
2269   DataArrayInt *desc=DataArrayInt::New();
2270   DataArrayInt *descIndx=DataArrayInt::New();
2271   DataArrayInt *revDesc=DataArrayInt::New();
2272   DataArrayInt *revDescIndx=DataArrayInt::New();
2273   //
2274   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2275   revDesc->decrRef();
2276   desc->decrRef();
2277   descIndx->decrRef();
2278   int nbOfCells=meshDM1->getNumberOfCells();
2279   const int *revDescIndxC=revDescIndx->getConstPointer();
2280   std::vector<int> boundaryCells;
2281   for(int i=0;i<nbOfCells;i++)
2282     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2283       boundaryCells.push_back(i);
2284   revDescIndx->decrRef();
2285   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2286   return ret;
2287 }
2288
2289 /*!
2290  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2291  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2292  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2293  */
2294 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2295 {
2296   checkFullyDefined();
2297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2301   //
2302   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2303   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2304   //
2305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2307   const int *revDescPtr=revDesc->getConstPointer();
2308   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2309   int nbOfCells=getNumberOfCells();
2310   std::vector<bool> ret1(nbOfCells,false);
2311   int sz=0;
2312   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2313     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2314       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2315   //
2316   DataArrayInt *ret2=DataArrayInt::New();
2317   ret2->alloc(sz,1);
2318   int *ret2Ptr=ret2->getPointer();
2319   sz=0;
2320   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2321     if(*it)
2322       *ret2Ptr++=sz;
2323   ret2->setName("BoundaryCells");
2324   return ret2;
2325 }
2326
2327 /*!
2328  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2329  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2330  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2331  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2332  *
2333  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2334  * This method returns the cells ids set s = s1 + s2 where:
2335  * 
2336  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2337  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2338  *
2339  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2340  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2341  *
2342  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2343  * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1+s2 \b into the \b cellIdsRk0 subset. To get the absolute ids of s1+s2, simply invoke
2344  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2345  */
2346 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2347 {
2348   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2350   checkConnectivityFullyDefined();
2351   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2352   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2356   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2358   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2359   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2360   DataArrayInt *idsOtherInConsti=0;
2361   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2363   if(!b)
2364     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2365   std::set<int> s1;
2366   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2367     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2370   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2371   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2373   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2374   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2375   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2376   neighThisPartAuto=0;
2377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2378   const int li[2]={0,1};
2379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2380   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2382   s_renum1->sort();
2383   //
2384   cellIdsRk0=s0arr.retn();
2385   cellIdsRk1=s_renum1.retn();
2386 }
2387
2388 /*!
2389  * 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
2390  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2391  * 
2392  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2393  */
2394 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2395 {
2396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2397   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2400   //
2401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2402   revDesc=0; desc=0; descIndx=0;
2403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2405   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2406 }
2407
2408 /*!
2409  * Finds nodes lying on the boundary of \a this mesh.
2410  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2411  *          nodes. The caller is to delete this array using decrRef() as it is no
2412  *          more needed.
2413  *  \throw If the coordinates array is not set.
2414  *  \throw If the nodal connectivity of cells is node defined.
2415  *
2416  *  \if ENABLE_EXAMPLES
2417  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2418  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2419  *  \endif
2420  */
2421 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2422 {
2423   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2424   return skin->computeFetchedNodeIds();
2425 }
2426
2427 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2428 {
2429   incrRef();
2430   return const_cast<MEDCouplingUMesh *>(this);
2431 }
2432
2433 /*!
2434  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2435  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2436  * 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.
2437  * 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.
2438  * 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.
2439  *
2440  * \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
2441  *             parameter is altered during the call.
2442  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2443  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2444  * \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.
2445  *
2446  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2447  */
2448 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2449                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2450 {
2451   checkFullyDefined();
2452   otherDimM1OnSameCoords.checkFullyDefined();
2453   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2454     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2455   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2456     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2457   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2458   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2461   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2462   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2463   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2466   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2467   //
2468   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2469   int nCells2 = m0Part2->getNumberOfCells();
2470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2471   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2472   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2473   DataArrayInt *tmp00=0,*tmp11=0;
2474   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2475   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighInit00(tmp00);
2476   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighIInit00(tmp11);
2477   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2478   DataArrayInt *idsTmp=0;
2479   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2481   if(!b)
2482     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2483   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2484   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2485   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2486   DataArrayInt *tmp0=0,*tmp1=0;
2487   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2488   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2489   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2491   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2492
2493
2494   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2495   int seed = 0, nIter = 0;
2496   int nIterMax = nCells2+1; // Safety net for the loop
2497   bool * hitCells = new bool[nCells2];
2498   for (int iii=0; iii<nCells2; iii++) hitCells[iii] = false;
2499   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum = DataArrayInt::New();
2500   cellsToModifyConn0_torenum->alloc(0,1);
2501   while (nIter < nIterMax)
2502     {
2503       if (std::find(hitCells, hitCells+nCells2, false) == hitCells+nCells2)
2504         break;
2505       // Connex zone without the crack (to compute the next seed really)
2506       int dnu;
2507       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2508       int cnt = 0;
2509       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2510         hitCells[*ptr] = true;
2511       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2512       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2513       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2514       // Compute next seed, i.e. a cell in another connex part:
2515       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2516       seed = comple->getIJ(0,0);
2517       nIter++;
2518     }
2519   delete[] hitCells;
2520   if (nIter >= nIterMax)
2521     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2522
2523   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2524   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2525   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2526   //
2527   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2528   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2529   nodeIdsToDuplicate=s3.retn();
2530 }
2531
2532 /*!
2533  * This method operates a modification of the connectivity and coords in \b this.
2534  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2535  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2536  * 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
2537  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2538  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2539  * 
2540  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2541  * 
2542  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2543  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2544  */
2545 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2546 {
2547   int nbOfNodes=getNumberOfNodes();
2548   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2549   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2550 }
2551
2552 /*!
2553  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2554  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2555  *
2556  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2557  *
2558  * \sa renumberNodesInConn
2559  */
2560 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2561 {
2562   checkConnectivityFullyDefined();
2563   int *conn(getNodalConnectivity()->getPointer());
2564   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2565   int nbOfCells(getNumberOfCells());
2566   for(int i=0;i<nbOfCells;i++)
2567     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2568       {
2569         int& node=conn[iconn];
2570         if(node>=0)//avoid polyhedron separator
2571           {
2572             node+=offset;
2573           }
2574       }
2575   _nodal_connec->declareAsNew();
2576   updateTime();
2577 }
2578
2579 /*!
2580  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2581  *  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
2582  *  of a big mesh.
2583  */
2584 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2585 {
2586   checkConnectivityFullyDefined();
2587   int *conn(getNodalConnectivity()->getPointer());
2588   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2589   int nbOfCells(getNumberOfCells());
2590   for(int i=0;i<nbOfCells;i++)
2591     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2592       {
2593         int& node=conn[iconn];
2594         if(node>=0)//avoid polyhedron separator
2595           {
2596             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2597             if(it!=newNodeNumbersO2N.end())
2598               {
2599                 node=(*it).second;
2600               }
2601             else
2602               {
2603                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2604                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2605               }
2606           }
2607       }
2608   _nodal_connec->declareAsNew();
2609   updateTime();
2610 }
2611
2612 /*!
2613  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2614  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2615  * This method is a generalization of shiftNodeNumbersInConn().
2616  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2617  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2618  *         this->getNumberOfNodes(), in "Old to New" mode. 
2619  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2620  *  \throw If the nodal connectivity of cells is not defined.
2621  *
2622  *  \if ENABLE_EXAMPLES
2623  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2624  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2625  *  \endif
2626  */
2627 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2628 {
2629   checkConnectivityFullyDefined();
2630   int *conn=getNodalConnectivity()->getPointer();
2631   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2632   int nbOfCells(getNumberOfCells());
2633   for(int i=0;i<nbOfCells;i++)
2634     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2635       {
2636         int& node=conn[iconn];
2637         if(node>=0)//avoid polyhedron separator
2638           {
2639             node=newNodeNumbersO2N[node];
2640           }
2641       }
2642   _nodal_connec->declareAsNew();
2643   updateTime();
2644 }
2645
2646 /*!
2647  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2648  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2649  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2650  * 
2651  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2652  */
2653 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2654 {
2655   checkConnectivityFullyDefined();
2656   int *conn=getNodalConnectivity()->getPointer();
2657   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2658   int nbOfCells=getNumberOfCells();
2659   for(int i=0;i<nbOfCells;i++)
2660     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2661       {
2662         int& node=conn[iconn];
2663         if(node>=0)//avoid polyhedron separator
2664           {
2665             node+=delta;
2666           }
2667       }
2668   _nodal_connec->declareAsNew();
2669   updateTime();
2670 }
2671
2672 /*!
2673  * This method operates a modification of the connectivity in \b this.
2674  * 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.
2675  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2676  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2677  * 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
2678  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2679  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2680  * 
2681  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2682  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2683  * 
2684  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2685  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2686  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2687  */
2688 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2689 {
2690   checkConnectivityFullyDefined();
2691   std::map<int,int> m;
2692   int val=offset;
2693   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2694     m[*work]=val;
2695   int *conn=getNodalConnectivity()->getPointer();
2696   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2697   int nbOfCells=getNumberOfCells();
2698   for(int i=0;i<nbOfCells;i++)
2699     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2700       {
2701         int& node=conn[iconn];
2702         if(node>=0)//avoid polyhedron separator
2703           {
2704             std::map<int,int>::iterator it=m.find(node);
2705             if(it!=m.end())
2706               node=(*it).second;
2707           }
2708       }
2709   updateTime();
2710 }
2711
2712 /*!
2713  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2714  *
2715  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2716  * After the call of this method the number of cells remains the same as before.
2717  *
2718  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2719  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2720  * be strictly in [0;this->getNumberOfCells()).
2721  *
2722  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2723  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2724  * should be contained in[0;this->getNumberOfCells()).
2725  * 
2726  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2727  */
2728 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2729 {
2730   checkConnectivityFullyDefined();
2731   int nbCells=getNumberOfCells();
2732   const int *array=old2NewBg;
2733   if(check)
2734     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2735   //
2736   const int *conn=_nodal_connec->getConstPointer();
2737   const int *connI=_nodal_connec_index->getConstPointer();
2738   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2739   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2740   const int *n2oPtr=n2o->begin();
2741   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2742   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2743   newConn->copyStringInfoFrom(*_nodal_connec);
2744   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2745   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2746   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2747   //
2748   int *newC=newConn->getPointer();
2749   int *newCI=newConnI->getPointer();
2750   int loc=0;
2751   newCI[0]=loc;
2752   for(int i=0;i<nbCells;i++)
2753     {
2754       int pos=n2oPtr[i];
2755       int nbOfElts=connI[pos+1]-connI[pos];
2756       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2757       loc+=nbOfElts;
2758       newCI[i+1]=loc;
2759     }
2760   //
2761   setConnectivity(newConn,newConnI);
2762   if(check)
2763     free(const_cast<int *>(array));
2764 }
2765
2766 /*!
2767  * Finds cells whose bounding boxes intersect a given bounding box.
2768  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2769  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2770  *         zMax (if in 3D). 
2771  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2772  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2773  *         extent of the bounding box of cell to produce an addition to this bounding box.
2774  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2775  *         cells. The caller is to delete this array using decrRef() as it is no more
2776  *         needed. 
2777  *  \throw If the coordinates array is not set.
2778  *  \throw If the nodal connectivity of cells is not defined.
2779  *
2780  *  \if ENABLE_EXAMPLES
2781  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2782  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2783  *  \endif
2784  */
2785 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2786 {
2787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2788   if(getMeshDimension()==-1)
2789     {
2790       elems->pushBackSilent(0);
2791       return elems.retn();
2792     }
2793   int dim=getSpaceDimension();
2794   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2795   const int* conn      = getNodalConnectivity()->getConstPointer();
2796   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2797   const double* coords = getCoords()->getConstPointer();
2798   int nbOfCells=getNumberOfCells();
2799   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2800     {
2801       for (int i=0; i<dim; i++)
2802         {
2803           elem_bb[i*2]=std::numeric_limits<double>::max();
2804           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2805         }
2806
2807       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2808         {
2809           int node= conn[inode];
2810           if(node>=0)//avoid polyhedron separator
2811             {
2812               for (int idim=0; idim<dim; idim++)
2813                 {
2814                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2815                     {
2816                       elem_bb[idim*2] = coords[node*dim+idim] ;
2817                     }
2818                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2819                     {
2820                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2821                     }
2822                 }
2823             }
2824         }
2825       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2826         elems->pushBackSilent(ielem);
2827     }
2828   return elems.retn();
2829 }
2830
2831 /*!
2832  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2833  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2834  * added in 'elems' parameter.
2835  */
2836 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2837 {
2838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2839   if(getMeshDimension()==-1)
2840     {
2841       elems->pushBackSilent(0);
2842       return elems.retn();
2843     }
2844   int dim=getSpaceDimension();
2845   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2846   const int* conn      = getNodalConnectivity()->getConstPointer();
2847   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2848   const double* coords = getCoords()->getConstPointer();
2849   int nbOfCells=getNumberOfCells();
2850   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2851     {
2852       for (int i=0; i<dim; i++)
2853         {
2854           elem_bb[i*2]=std::numeric_limits<double>::max();
2855           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2856         }
2857
2858       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2859         {
2860           int node= conn[inode];
2861           if(node>=0)//avoid polyhedron separator
2862             {
2863               for (int idim=0; idim<dim; idim++)
2864                 {
2865                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2866                     {
2867                       elem_bb[idim*2] = coords[node*dim+idim] ;
2868                     }
2869                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2870                     {
2871                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2872                     }
2873                 }
2874             }
2875         }
2876       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2877         elems->pushBackSilent(ielem);
2878     }
2879   return elems.retn();
2880 }
2881
2882 /*!
2883  * Returns a type of a cell by its id.
2884  *  \param [in] cellId - the id of the cell of interest.
2885  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2886  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2887  */
2888 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2889 {
2890   const int *ptI=_nodal_connec_index->getConstPointer();
2891   const int *pt=_nodal_connec->getConstPointer();
2892   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2893     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2894   else
2895     {
2896       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2897       throw INTERP_KERNEL::Exception(oss.str().c_str());
2898     }
2899 }
2900
2901 /*!
2902  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2903  * This method does not throw exception if geometric type \a type is not in \a this.
2904  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2905  * The coordinates array is not considered here.
2906  *
2907  * \param [in] type the geometric type
2908  * \return cell ids in this having geometric type \a type.
2909  */
2910 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2911 {
2912
2913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2914   ret->alloc(0,1);
2915   checkConnectivityFullyDefined();
2916   int nbCells=getNumberOfCells();
2917   int mdim=getMeshDimension();
2918   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2919   if(mdim!=(int)cm.getDimension())
2920     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2921   const int *ptI=_nodal_connec_index->getConstPointer();
2922   const int *pt=_nodal_connec->getConstPointer();
2923   for(int i=0;i<nbCells;i++)
2924     {
2925       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2926         ret->pushBackSilent(i);
2927     }
2928   return ret.retn();
2929 }
2930
2931 /*!
2932  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2933  */
2934 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2935 {
2936   const int *ptI=_nodal_connec_index->getConstPointer();
2937   const int *pt=_nodal_connec->getConstPointer();
2938   int nbOfCells=getNumberOfCells();
2939   int ret=0;
2940   for(int i=0;i<nbOfCells;i++)
2941     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2942       ret++;
2943   return ret;
2944 }
2945
2946 /*!
2947  * Returns the nodal connectivity of a given cell.
2948  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2949  * all returned node ids can be used in getCoordinatesOfNode().
2950  *  \param [in] cellId - an id of the cell of interest.
2951  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2952  *         cleared before the appending.
2953  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2954  */
2955 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2956 {
2957   const int *ptI=_nodal_connec_index->getConstPointer();
2958   const int *pt=_nodal_connec->getConstPointer();
2959   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2960     if(*w>=0)
2961       conn.push_back(*w);
2962 }
2963
2964 std::string MEDCouplingUMesh::simpleRepr() const
2965 {
2966   static const char msg0[]="No coordinates specified !";
2967   std::ostringstream ret;
2968   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2969   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2970   int tmpp1,tmpp2;
2971   double tt=getTime(tmpp1,tmpp2);
2972   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2973   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2974   if(_mesh_dim>=-1)
2975     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2976   else
2977     { ret << " Mesh dimension has not been set or is invalid !"; }
2978   if(_coords!=0)
2979     {
2980       const int spaceDim=getSpaceDimension();
2981       ret << spaceDim << "\nInfo attached on space dimension : ";
2982       for(int i=0;i<spaceDim;i++)
2983         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2984       ret << "\n";
2985     }
2986   else
2987     ret << msg0 << "\n";
2988   ret << "Number of nodes : ";
2989   if(_coords!=0)
2990     ret << getNumberOfNodes() << "\n";
2991   else
2992     ret << msg0 << "\n";
2993   ret << "Number of cells : ";
2994   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2995     ret << getNumberOfCells() << "\n";
2996   else
2997     ret << "No connectivity specified !" << "\n";
2998   ret << "Cell types present : ";
2999   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3000     {
3001       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3002       ret << cm.getRepr() << " ";
3003     }
3004   ret << "\n";
3005   return ret.str();
3006 }
3007
3008 std::string MEDCouplingUMesh::advancedRepr() const
3009 {
3010   std::ostringstream ret;
3011   ret << simpleRepr();
3012   ret << "\nCoordinates array : \n___________________\n\n";
3013   if(_coords)
3014     _coords->reprWithoutNameStream(ret);
3015   else
3016     ret << "No array set !\n";
3017   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3018   reprConnectivityOfThisLL(ret);
3019   return ret.str();
3020 }
3021
3022 /*!
3023  * This method returns a C++ code that is a dump of \a this.
3024  * This method will throw if this is not fully defined.
3025  */
3026 std::string MEDCouplingUMesh::cppRepr() const
3027 {
3028   static const char coordsName[]="coords";
3029   static const char connName[]="conn";
3030   static const char connIName[]="connI";
3031   checkFullyDefined();
3032   std::ostringstream ret; ret << "// coordinates" << std::endl;
3033   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3034   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3035   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3036   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3037   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3038   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3039   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3040   return ret.str();
3041 }
3042
3043 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3044 {
3045   std::ostringstream ret;
3046   reprConnectivityOfThisLL(ret);
3047   return ret.str();
3048 }
3049
3050 /*!
3051  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3052  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3053  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3054  * some algos).
3055  * 
3056  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3057  * 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
3058  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3059  */
3060 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3061 {
3062   int mdim=getMeshDimension();
3063   if(mdim<0)
3064     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3065   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3066   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3067   bool needToCpyCT=true;
3068   if(!_nodal_connec)
3069     {
3070       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3071       needToCpyCT=false;
3072     }
3073   else
3074     {
3075       tmp1=_nodal_connec;
3076       tmp1->incrRef();
3077     }
3078   if(!_nodal_connec_index)
3079     {
3080       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3081       needToCpyCT=false;
3082     }
3083   else
3084     {
3085       tmp2=_nodal_connec_index;
3086       tmp2->incrRef();
3087     }
3088   ret->setConnectivity(tmp1,tmp2,false);
3089   if(needToCpyCT)
3090     ret->_types=_types;
3091   if(!_coords)
3092     {
3093       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3094       ret->setCoords(coords);
3095     }
3096   else
3097     ret->setCoords(_coords);
3098   return ret.retn();
3099 }
3100
3101 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3102 {
3103   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3104     {
3105       int nbOfCells=getNumberOfCells();
3106       const int *c=_nodal_connec->getConstPointer();
3107       const int *ci=_nodal_connec_index->getConstPointer();
3108       for(int i=0;i<nbOfCells;i++)
3109         {
3110           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3111           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3112           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3113           stream << "\n";
3114         }
3115     }
3116   else
3117     stream << "Connectivity not defined !\n";
3118 }
3119
3120 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3121 {
3122   const int *ptI=_nodal_connec_index->getConstPointer();
3123   const int *pt=_nodal_connec->getConstPointer();
3124   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3125     return ptI[cellId+1]-ptI[cellId]-1;
3126   else
3127     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3128 }
3129
3130 /*!
3131  * Returns types of cells of the specified part of \a this mesh.
3132  * This method avoids computing sub-mesh explicitely to get its types.
3133  *  \param [in] begin - an array of cell ids of interest.
3134  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3135  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3136  *         describing the cell types. 
3137  *  \throw If the coordinates array is not set.
3138  *  \throw If the nodal connectivity of cells is not defined.
3139  *  \sa getAllGeoTypes()
3140  */
3141 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3142 {
3143   checkFullyDefined();
3144   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3145   const int *conn=_nodal_connec->getConstPointer();
3146   const int *connIndex=_nodal_connec_index->getConstPointer();
3147   for(const int *w=begin;w!=end;w++)
3148     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3149   return ret;
3150 }
3151
3152 /*!
3153  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3154  * a set of types of cells constituting \a this mesh. 
3155  * This method is for advanced users having prepared their connectivity before. For
3156  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3157  *  \param [in] conn - the nodal connectivity array. 
3158  *  \param [in] connIndex - the nodal connectivity index array.
3159  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3160  *         mesh is updated.
3161  */
3162 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3163 {
3164   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3165   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3166   if(isComputingTypes)
3167     computeTypes();
3168   declareAsNew();
3169 }
3170
3171 /*!
3172  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3173  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3174  */
3175 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3176     _nodal_connec(0),_nodal_connec_index(0),
3177     _types(other._types)
3178 {
3179   if(other._nodal_connec)
3180     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3181   if(other._nodal_connec_index)
3182     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3183 }
3184
3185 MEDCouplingUMesh::~MEDCouplingUMesh()
3186 {
3187   if(_nodal_connec)
3188     _nodal_connec->decrRef();
3189   if(_nodal_connec_index)
3190     _nodal_connec_index->decrRef();
3191 }
3192
3193 /*!
3194  * Recomputes a set of cell types of \a this mesh. For more info see
3195  * \ref MEDCouplingUMeshNodalConnectivity.
3196  */
3197 void MEDCouplingUMesh::computeTypes()
3198 {
3199   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3200 }
3201
3202 /*!
3203  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3204  */
3205 void MEDCouplingUMesh::checkFullyDefined() const
3206 {
3207   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3208     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3209 }
3210
3211 /*!
3212  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3213  */
3214 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3215 {
3216   if(!_nodal_connec_index || !_nodal_connec)
3217     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3218 }
3219
3220 /*!
3221  * Returns a number of cells constituting \a this mesh. 
3222  *  \return int - the number of cells in \a this mesh.
3223  *  \throw If the nodal connectivity of cells is not defined.
3224  */
3225 int MEDCouplingUMesh::getNumberOfCells() const
3226
3227   if(_nodal_connec_index)
3228     return _nodal_connec_index->getNumberOfTuples()-1;
3229   else
3230     if(_mesh_dim==-1)
3231       return 1;
3232     else
3233       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3234 }
3235
3236 /*!
3237  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3238  * mesh. For more info see \ref MEDCouplingMeshesPage.
3239  *  \return int - the dimension of \a this mesh.
3240  *  \throw If the mesh dimension is not defined using setMeshDimension().
3241  */
3242 int MEDCouplingUMesh::getMeshDimension() const
3243 {
3244   if(_mesh_dim<-1)
3245     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3246   return _mesh_dim;
3247 }
3248
3249 /*!
3250  * Returns a length of the nodal connectivity array.
3251  * This method is for test reason. Normally the integer returned is not useable by
3252  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3253  *  \return int - the length of the nodal connectivity array.
3254  */
3255 int MEDCouplingUMesh::getMeshLength() const
3256 {
3257   return _nodal_connec->getNbOfElems();
3258 }
3259
3260 /*!
3261  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3262  */
3263 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3264 {
3265   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3266   tinyInfo.push_back(getMeshDimension());
3267   tinyInfo.push_back(getNumberOfCells());
3268   if(_nodal_connec)
3269     tinyInfo.push_back(getMeshLength());
3270   else
3271     tinyInfo.push_back(-1);
3272 }
3273
3274 /*!
3275  * First step of unserialization process.
3276  */
3277 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3278 {
3279   return tinyInfo[6]<=0;
3280 }
3281
3282 /*!
3283  * Second step of serialization process.
3284  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3285  */
3286 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3287 {
3288   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3289   if(tinyInfo[5]!=-1)
3290     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3291 }
3292
3293 /*!
3294  * Third and final step of serialization process.
3295  */
3296 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3297 {
3298   MEDCouplingPointSet::serialize(a1,a2);
3299   if(getMeshDimension()>-1)
3300     {
3301       a1=DataArrayInt::New();
3302       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3303       int *ptA1=a1->getPointer();
3304       const int *conn=getNodalConnectivity()->getConstPointer();
3305       const int *index=getNodalConnectivityIndex()->getConstPointer();
3306       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3307       std::copy(conn,conn+getMeshLength(),ptA1);
3308     }
3309   else
3310     a1=0;
3311 }
3312
3313 /*!
3314  * Second and final unserialization process.
3315  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3316  */
3317 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3318 {
3319   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3320   setMeshDimension(tinyInfo[5]);
3321   if(tinyInfo[7]!=-1)
3322     {
3323       // Connectivity
3324       const int *recvBuffer=a1->getConstPointer();
3325       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3326       myConnecIndex->alloc(tinyInfo[6]+1,1);
3327       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3328       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3329       myConnec->alloc(tinyInfo[7],1);
3330       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3331       setConnectivity(myConnec, myConnecIndex);
3332     }
3333 }
3334
3335 /*!
3336  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3337  * CellIds are given using range specified by a start an end and step.
3338  */
3339 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3340 {
3341   checkFullyDefined();
3342   int ncell=getNumberOfCells();
3343   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3344   ret->_mesh_dim=_mesh_dim;
3345   ret->setCoords(_coords);
3346   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3348   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3349   int work=start;
3350   const int *conn=_nodal_connec->getConstPointer();
3351   const int *connIndex=_nodal_connec_index->getConstPointer();
3352   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3353     {
3354       if(work>=0 && work<ncell)
3355         {
3356           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3357         }
3358       else
3359         {
3360           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3361           throw INTERP_KERNEL::Exception(oss.str().c_str());
3362         }
3363     }
3364   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3365   int *newConnPtr=newConn->getPointer();
3366   std::set<INTERP_KERNEL::NormalizedCellType> types;
3367   work=start;
3368   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3369     {
3370       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3371       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3372     }
3373   ret->setConnectivity(newConn,newConnI,false);
3374   ret->_types=types;
3375   ret->copyTinyInfoFrom(this);
3376   return ret.retn();
3377 }
3378
3379 /*!
3380  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3381  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3382  * The return newly allocated mesh will share the same coordinates as \a this.
3383  */
3384 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3385 {
3386   checkConnectivityFullyDefined();
3387   int ncell=getNumberOfCells();
3388   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3389   ret->_mesh_dim=_mesh_dim;
3390   ret->setCoords(_coords);
3391   std::size_t nbOfElemsRet=std::distance(begin,end);
3392   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3393   connIndexRet[0]=0;
3394   const int *conn=_nodal_connec->getConstPointer();
3395   const int *connIndex=_nodal_connec_index->getConstPointer();
3396   int newNbring=0;
3397   for(const int *work=begin;work!=end;work++,newNbring++)
3398     {
3399       if(*work>=0 && *work<ncell)
3400         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3401       else
3402         {
3403           free(connIndexRet);
3404           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3405           throw INTERP_KERNEL::Exception(oss.str().c_str());
3406         }
3407     }
3408   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3409   int *connRetWork=connRet;
3410   std::set<INTERP_KERNEL::NormalizedCellType> types;
3411   for(const int *work=begin;work!=end;work++)
3412     {
3413       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3414       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3415     }
3416   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3417   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3419   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3420   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3421   ret->_types=types;
3422   ret->copyTinyInfoFrom(this);
3423   return ret.retn();
3424 }
3425
3426 /*!
3427  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3428  * mesh.<br>
3429  * For 1D cells, the returned field contains lengths.<br>
3430  * For 2D cells, the returned field contains areas.<br>
3431  * For 3D cells, the returned field contains volumes.
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  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3435  *         and one time . The caller is to delete this field using decrRef() as it is no
3436  *         more needed.
3437  */
3438 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3439 {
3440   std::string name="MeasureOfMesh_";
3441   name+=getName();
3442   int nbelem=getNumberOfCells();
3443   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3444   field->setName(name);
3445   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3446   array->alloc(nbelem,1);
3447   double *area_vol=array->getPointer();
3448   field->setArray(array) ; array=0;
3449   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3450   field->synchronizeTimeWithMesh();
3451   if(getMeshDimension()!=-1)
3452     {
3453       int ipt;
3454       INTERP_KERNEL::NormalizedCellType type;
3455       int dim_space=getSpaceDimension();
3456       const double *coords=getCoords()->getConstPointer();
3457       const int *connec=getNodalConnectivity()->getConstPointer();
3458       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3459       for(int iel=0;iel<nbelem;iel++)
3460         {
3461           ipt=connec_index[iel];
3462           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3463           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);
3464         }
3465       if(isAbs)
3466         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3467     }
3468   else
3469     {
3470       area_vol[0]=std::numeric_limits<double>::max();
3471     }
3472   return field.retn();
3473 }
3474
3475 /*!
3476  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3477  * mesh.<br>
3478  * For 1D cells, the returned array contains lengths.<br>
3479  * For 2D cells, the returned array contains areas.<br>
3480  * For 3D cells, the returned array contains volumes.
3481  * This method avoids building explicitly a part of \a this mesh to perform the work.
3482  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3483  *         orientation, i.e. the volume is always positive.
3484  *  \param [in] begin - an array of cell ids of interest.
3485  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3486  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3487  *          delete this array using decrRef() as it is no more needed.
3488  * 
3489  *  \if ENABLE_EXAMPLES
3490  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3491  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3492  *  \endif
3493  *  \sa getMeasureField()
3494  */
3495 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3496 {
3497   std::string name="PartMeasureOfMesh_";
3498   name+=getName();
3499   int nbelem=(int)std::distance(begin,end);
3500   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3501   array->setName(name);
3502   array->alloc(nbelem,1);
3503   double *area_vol=array->getPointer();
3504   if(getMeshDimension()!=-1)
3505     {
3506       int ipt;
3507       INTERP_KERNEL::NormalizedCellType type;
3508       int dim_space=getSpaceDimension();
3509       const double *coords=getCoords()->getConstPointer();
3510       const int *connec=getNodalConnectivity()->getConstPointer();
3511       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3512       for(const int *iel=begin;iel!=end;iel++)
3513         {
3514           ipt=connec_index[*iel];
3515           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3516           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3517         }
3518       if(isAbs)
3519         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3520     }
3521   else
3522     {
3523       area_vol[0]=std::numeric_limits<double>::max();
3524     }
3525   return array.retn();
3526 }
3527
3528 /*!
3529  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3530  * \a this one. The returned field contains the dual cell volume for each corresponding
3531  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3532  *  the dual mesh in P1 sens of \a this.<br>
3533  * For 1D cells, the returned field contains lengths.<br>
3534  * For 2D cells, the returned field contains areas.<br>
3535  * For 3D cells, the returned field contains volumes.
3536  * This method is useful to check "P1*" conservative interpolators.
3537  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3538  *         orientation, i.e. the volume is always positive.
3539  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3540  *          nodes and one time. The caller is to delete this array using decrRef() as
3541  *          it is no more needed.
3542  */
3543 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3544 {
3545   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3546   std::string name="MeasureOnNodeOfMesh_";
3547   name+=getName();
3548   int nbNodes=getNumberOfNodes();
3549   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3550   double cst=1./((double)getMeshDimension()+1.);
3551   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3552   array->alloc(nbNodes,1);
3553   double *valsToFill=array->getPointer();
3554   std::fill(valsToFill,valsToFill+nbNodes,0.);
3555   const double *values=tmp->getArray()->getConstPointer();
3556   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3558   getReverseNodalConnectivity(da,daInd);
3559   const int *daPtr=da->getConstPointer();
3560   const int *daIPtr=daInd->getConstPointer();
3561   for(int i=0;i<nbNodes;i++)
3562     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3563       valsToFill[i]+=cst*values[*cell];
3564   ret->setMesh(this);
3565   ret->setArray(array);
3566   return ret.retn();
3567 }
3568
3569 /*!
3570  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3571  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3572  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3573  * and are normalized.
3574  * <br> \a this can be either 
3575  * - a  2D mesh in 2D or 3D space or 
3576  * - an 1D mesh in 2D space.
3577  * 
3578  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3579  *          cells and one time. The caller is to delete this field using decrRef() as
3580  *          it is no more needed.
3581  *  \throw If the nodal connectivity of cells is not defined.
3582  *  \throw If the coordinates array is not set.
3583  *  \throw If the mesh dimension is not set.
3584  *  \throw If the mesh and space dimension is not as specified above.
3585  */
3586 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3587 {
3588   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3589     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3590   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3591   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3592   int nbOfCells=getNumberOfCells();
3593   int nbComp=getMeshDimension()+1;
3594   array->alloc(nbOfCells,nbComp);
3595   double *vals=array->getPointer();
3596   const int *connI=_nodal_connec_index->getConstPointer();
3597   const int *conn=_nodal_connec->getConstPointer();
3598   const double *coords=_coords->getConstPointer();
3599   if(getMeshDimension()==2)
3600     {
3601       if(getSpaceDimension()==3)
3602         {
3603           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3604           const double *locPtr=loc->getConstPointer();
3605           for(int i=0;i<nbOfCells;i++,vals+=3)
3606             {
3607               int offset=connI[i];
3608               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3609               double n=INTERP_KERNEL::norm<3>(vals);
3610               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3611             }
3612         }
3613       else
3614         {
3615           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3616           const double *isAbsPtr=isAbs->getArray()->begin();
3617           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3618             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3619         }
3620     }
3621   else//meshdimension==1
3622     {
3623       double tmp[2];
3624       for(int i=0;i<nbOfCells;i++)
3625         {
3626           int offset=connI[i];
3627           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3628           double n=INTERP_KERNEL::norm<2>(tmp);
3629           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3630           *vals++=-tmp[1];
3631           *vals++=tmp[0];
3632         }
3633     }
3634   ret->setArray(array);
3635   ret->setMesh(this);
3636   ret->synchronizeTimeWithSupport();
3637   return ret.retn();
3638 }
3639
3640 /*!
3641  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3642  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3643  * and are normalized.
3644  * <br> \a this can be either 
3645  * - a  2D mesh in 2D or 3D space or 
3646  * - an 1D mesh in 2D space.
3647  * 
3648  * This method avoids building explicitly a part of \a this mesh to perform the work.
3649  *  \param [in] begin - an array of cell ids of interest.
3650  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3651  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3652  *          cells and one time. The caller is to delete this field using decrRef() as
3653  *          it is no more needed.
3654  *  \throw If the nodal connectivity of cells is not defined.
3655  *  \throw If the coordinates array is not set.
3656  *  \throw If the mesh dimension is not set.
3657  *  \throw If the mesh and space dimension is not as specified above.
3658  *  \sa buildOrthogonalField()
3659  *
3660  *  \if ENABLE_EXAMPLES
3661  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3662  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3663  *  \endif
3664  */
3665 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3666 {
3667   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3668     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3669   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3670   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3671   std::size_t nbelems=std::distance(begin,end);
3672   int nbComp=getMeshDimension()+1;
3673   array->alloc((int)nbelems,nbComp);
3674   double *vals=array->getPointer();
3675   const int *connI=_nodal_connec_index->getConstPointer();
3676   const int *conn=_nodal_connec->getConstPointer();
3677   const double *coords=_coords->getConstPointer();
3678   if(getMeshDimension()==2)
3679     {
3680       if(getSpaceDimension()==3)
3681         {
3682           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3683           const double *locPtr=loc->getConstPointer();
3684           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3685             {
3686               int offset=connI[*i];
3687               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3688               double n=INTERP_KERNEL::norm<3>(vals);
3689               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3690             }
3691         }
3692       else
3693         {
3694           for(std::size_t i=0;i<nbelems;i++)
3695             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3696         }
3697     }
3698   else//meshdimension==1
3699     {
3700       double tmp[2];
3701       for(const int *i=begin;i!=end;i++)
3702         {
3703           int offset=connI[*i];
3704           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3705           double n=INTERP_KERNEL::norm<2>(tmp);
3706           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3707           *vals++=-tmp[1];
3708           *vals++=tmp[0];
3709         }
3710     }
3711   ret->setArray(array);
3712   ret->setMesh(this);
3713   ret->synchronizeTimeWithSupport();
3714   return ret.retn();
3715 }
3716
3717 /*!
3718  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3719  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3720  * and are \b not normalized.
3721  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3722  *          cells and one time. The caller is to delete this field using decrRef() as
3723  *          it is no more needed.
3724  *  \throw If the nodal connectivity of cells is not defined.
3725  *  \throw If the coordinates array is not set.
3726  *  \throw If \a this->getMeshDimension() != 1.
3727  *  \throw If \a this mesh includes cells of type other than SEG2.
3728  */
3729 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3730 {
3731   if(getMeshDimension()!=1)
3732     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3733   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3734     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3735   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3736   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3737   int nbOfCells=getNumberOfCells();
3738   int spaceDim=getSpaceDimension();
3739   array->alloc(nbOfCells,spaceDim);
3740   double *pt=array->getPointer();
3741   const double *coo=getCoords()->getConstPointer();
3742   std::vector<int> conn;
3743   conn.reserve(2);
3744   for(int i=0;i<nbOfCells;i++)
3745     {
3746       conn.resize(0);
3747       getNodeIdsOfCell(i,conn);
3748       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3749     }
3750   ret->setArray(array);
3751   ret->setMesh(this);
3752   ret->synchronizeTimeWithSupport();
3753   return ret.retn();
3754 }
3755
3756 /*!
3757  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3758  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3759  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3760  * from. If a result face is shared by two 3D cells, then the face in included twice in
3761  * the result mesh.
3762  *  \param [in] origin - 3 components of a point defining location of the plane.
3763  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3764  *         must be greater than 1e-6.
3765  *  \param [in] eps - half-thickness of the plane.
3766  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3767  *         producing correspondent 2D cells. The caller is to delete this array
3768  *         using decrRef() as it is no more needed.
3769  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3770  *         not share the node coordinates array with \a this mesh. The caller is to
3771  *         delete this mesh using decrRef() as it is no more needed.  
3772  *  \throw If the coordinates array is not set.
3773  *  \throw If the nodal connectivity of cells is not defined.
3774  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3775  *  \throw If magnitude of \a vec is less than 1e-6.
3776  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3777  *  \throw If \a this includes quadratic cells.
3778  */
3779 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3780 {
3781   checkFullyDefined();
3782   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3783     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3785   if(candidates->empty())
3786     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3787   std::vector<int> nodes;
3788   DataArrayInt *cellIds1D=0;
3789   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3790   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3791   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3793   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3794   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3795   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3796   revDesc2=0; revDescIndx2=0;
3797   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3798   revDesc1=0; revDescIndx1=0;
3799   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3800   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3801   //
3802   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3803   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3804     cut3DCurve[*it]=-1;
3805   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3806   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3807   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3808                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3809                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3811   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3812   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3813   if(cellIds2->empty())
3814     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3815   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3816   ret->setCoords(mDesc1->getCoords());
3817   ret->setConnectivity(conn,connI,true);
3818   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3819   return ret.retn();
3820 }
3821
3822 /*!
3823  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3824 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
3825 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3826 the result mesh.
3827  *  \param [in] origin - 3 components of a point defining location of the plane.
3828  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3829  *         must be greater than 1e-6.
3830  *  \param [in] eps - half-thickness of the plane.
3831  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3832  *         producing correspondent segments. The caller is to delete this array
3833  *         using decrRef() as it is no more needed.
3834  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3835  *         mesh in 3D space. This mesh does not share the node coordinates array with
3836  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3837  *         no more needed. 
3838  *  \throw If the coordinates array is not set.
3839  *  \throw If the nodal connectivity of cells is not defined.
3840  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3841  *  \throw If magnitude of \a vec is less than 1e-6.
3842  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3843  *  \throw If \a this includes quadratic cells.
3844  */
3845 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3846 {
3847   checkFullyDefined();
3848   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3851   if(candidates->empty())
3852     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3853   std::vector<int> nodes;
3854   DataArrayInt *cellIds1D=0;
3855   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3856   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3858   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3859   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3860   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3861   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3862   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3863   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3864   //
3865   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3866   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3867     cut3DCurve[*it]=-1;
3868   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3869   int ncellsSub=subMesh->getNumberOfCells();
3870   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3871   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3872                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3873                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3874   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3875   conn->alloc(0,1);
3876   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3877   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3878   for(int i=0;i<ncellsSub;i++)
3879     {
3880       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3881         {
3882           if(cut3DSurf[i].first!=-2)
3883             {
3884               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3885               connI->pushBackSilent(conn->getNumberOfTuples());
3886               cellIds2->pushBackSilent(i);
3887             }
3888           else
3889             {
3890               int cellId3DSurf=cut3DSurf[i].second;
3891               int offset=nodalI[cellId3DSurf]+1;
3892               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3893               for(int j=0;j<nbOfEdges;j++)
3894                 {
3895                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3896                   connI->pushBackSilent(conn->getNumberOfTuples());
3897                   cellIds2->pushBackSilent(cellId3DSurf);
3898                 }
3899             }
3900         }
3901     }
3902   if(cellIds2->empty())
3903     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3904   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3905   ret->setCoords(mDesc1->getCoords());
3906   ret->setConnectivity(conn,connI,true);
3907   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3908   return ret.retn();
3909 }
3910
3911 /*!
3912  * Finds cells whose bounding boxes intersect a given plane.
3913  *  \param [in] origin - 3 components of a point defining location of the plane.
3914  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3915  *         must be greater than 1e-6.
3916  *  \param [in] eps - half-thickness of the plane.
3917  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3918  *         cells. The caller is to delete this array using decrRef() as it is no more
3919  *         needed.
3920  *  \throw If the coordinates array is not set.
3921  *  \throw If the nodal connectivity of cells is not defined.
3922  *  \throw If \a this->getSpaceDimension() != 3.
3923  *  \throw If magnitude of \a vec is less than 1e-6.
3924  *  \sa buildSlice3D()
3925  */
3926 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3927 {
3928   checkFullyDefined();
3929   if(getSpaceDimension()!=3)
3930     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3931   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3932   if(normm<1e-6)
3933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3934   double vec2[3];
3935   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3936   double angle=acos(vec[2]/normm);
3937   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3938   double bbox[6];
3939   if(angle>eps)
3940     {
3941       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3942       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3943       if(normm2/normm>1e-6)
3944         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3945       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3946       mw->setCoords(coo);
3947       mw->getBoundingBox(bbox);
3948       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3949       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3950     }
3951   else
3952     {
3953       getBoundingBox(bbox);
3954       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3955       cellIds=getCellsInBoundingBox(bbox,eps);
3956     }
3957   return cellIds.retn();
3958 }
3959
3960 /*!
3961  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3962  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3963  * No consideration of coordinate is done by this method.
3964  * 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)
3965  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3966  */
3967 bool MEDCouplingUMesh::isContiguous1D() const
3968 {
3969   if(getMeshDimension()!=1)
3970     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3971   int nbCells=getNumberOfCells();
3972   if(nbCells<1)
3973     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3974   const int *connI=_nodal_connec_index->getConstPointer();
3975   const int *conn=_nodal_connec->getConstPointer();
3976   int ref=conn[connI[0]+2];
3977   for(int i=1;i<nbCells;i++)
3978     {
3979       if(conn[connI[i]+1]!=ref)
3980         return false;
3981       ref=conn[connI[i]+2];
3982     }
3983   return true;
3984 }
3985
3986 /*!
3987  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3988  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3989  * \param pt reference point of the line
3990  * \param v normalized director vector of the line
3991  * \param eps max precision before throwing an exception
3992  * \param res output of size this->getNumberOfCells
3993  */
3994 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3995 {
3996   if(getMeshDimension()!=1)
3997     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3998   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3999     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4000   if(getSpaceDimension()!=3)
4001     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4002   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4003   const double *fPtr=f->getArray()->getConstPointer();
4004   double tmp[3];
4005   for(int i=0;i<getNumberOfCells();i++)
4006     {
4007       const double *tmp1=fPtr+3*i;
4008       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4009       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4010       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4011       double n1=INTERP_KERNEL::norm<3>(tmp);
4012       n1/=INTERP_KERNEL::norm<3>(tmp1);
4013       if(n1>eps)
4014         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4015     }
4016   const double *coo=getCoords()->getConstPointer();
4017   for(int i=0;i<getNumberOfNodes();i++)
4018     {
4019       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4020       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4021       res[i]=std::accumulate(tmp,tmp+3,0.);
4022     }
4023 }
4024
4025 /*!
4026  * 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. 
4027  * \a this is expected to be a mesh so that its space dimension is equal to its
4028  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4029  * 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).
4030  *
4031  * 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
4032  * 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).
4033  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4034  *
4035  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4036  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4037  *
4038  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4039  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4040  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4041  * \return the positive value of the distance.
4042  * \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
4043  * dimension - 1.
4044  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4045  */
4046 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4047 {
4048   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4049   if(meshDim!=spaceDim-1)
4050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4051   if(meshDim!=2 && meshDim!=1)
4052     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4053   checkFullyDefined();
4054   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4055     { 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()); }
4056   DataArrayInt *ret1=0;
4057   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4058   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4059   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4060   cellId=*ret1Safe->begin();
4061   return *ret0->begin();
4062 }
4063
4064 /*!
4065  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4066  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4067  * 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
4068  * 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).
4069  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4070  * 
4071  * \a this is expected to be a mesh so that its space dimension is equal to its
4072  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4073  * 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).
4074  *
4075  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4076  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4077  *
4078  * \param [in] pts the list of points in which each tuple represents a point
4079  * \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.
4080  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4081  * \throw if number of components of \a pts is not equal to the space dimension.
4082  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4083  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4084  */
4085 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4086 {
4087   if(!pts)
4088     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4089   pts->checkAllocated();
4090   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4091   if(meshDim!=spaceDim-1)
4092     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4093   if(meshDim!=2 && meshDim!=1)
4094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4095   if(pts->getNumberOfComponents()!=spaceDim)
4096     {
4097       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4098       throw INTERP_KERNEL::Exception(oss.str().c_str());
4099     }
4100   checkFullyDefined();
4101   int nbCells=getNumberOfCells();
4102   if(nbCells==0)
4103     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4104   int nbOfPts=pts->getNumberOfTuples();
4105   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4107   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4108   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4109   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4110   const double *bbox(bboxArr->begin());
4111   switch(spaceDim)
4112   {
4113     case 3:
4114       {
4115         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4116         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4117           {
4118             double x=std::numeric_limits<double>::max();
4119             std::vector<int> elems;
4120             myTree.getMinDistanceOfMax(ptsPtr,x);
4121             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4122             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4123           }
4124         break;
4125       }
4126     case 2:
4127       {
4128         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4129         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4130           {
4131             double x=std::numeric_limits<double>::max();
4132             std::vector<int> elems;
4133             myTree.getMinDistanceOfMax(ptsPtr,x);
4134             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4135             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4136           }
4137         break;
4138       }
4139     default:
4140       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4141   }
4142   cellIds=ret1.retn();
4143   return ret0.retn();
4144 }
4145
4146 /*!
4147  * \param [in] pt the start pointer (included) of the coordinates of the point
4148  * \param [in] cellIdsBg the start pointer (included) of cellIds
4149  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4150  * \param [in] nc nodal connectivity
4151  * \param [in] ncI nodal connectivity index
4152  * \param [in,out] ret0 the min distance between \a this and the external input point
4153  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4154  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4155  */
4156 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)
4157 {
4158   cellId=-1;
4159   ret0=std::numeric_limits<double>::max();
4160   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4161     {
4162       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4163       {
4164         case INTERP_KERNEL::NORM_TRI3:
4165           {
4166             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4167             if(tmp<ret0)
4168               { ret0=tmp; cellId=*zeCell; }
4169             break;
4170           }
4171         case INTERP_KERNEL::NORM_QUAD4:
4172         case INTERP_KERNEL::NORM_POLYGON:
4173           {
4174             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4175             if(tmp<ret0)
4176               { ret0=tmp; cellId=*zeCell; }
4177             break;
4178           }
4179         default:
4180           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4181       }
4182     }
4183 }
4184
4185 /*!
4186  * \param [in] pt the start pointer (included) of the coordinates of the point
4187  * \param [in] cellIdsBg the start pointer (included) of cellIds
4188  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4189  * \param [in] nc nodal connectivity
4190  * \param [in] ncI nodal connectivity index
4191  * \param [in,out] ret0 the min distance between \a this and the external input point
4192  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4193  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4194  */
4195 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)
4196 {
4197   cellId=-1;
4198   ret0=std::numeric_limits<double>::max();
4199   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4200     {
4201       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4202       {
4203         case INTERP_KERNEL::NORM_SEG2:
4204           {
4205             std::size_t uselessEntry=0;
4206             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4207             tmp=sqrt(tmp);
4208             if(tmp<ret0)
4209               { ret0=tmp; cellId=*zeCell; }
4210             break;
4211           }
4212         default:
4213           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4214       }
4215     }
4216 }
4217
4218 /*!
4219  * Finds cells in contact with a ball (i.e. a point with precision). 
4220  * 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.
4221  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4222  *
4223  * \warning This method is suitable if the caller intends to evaluate only one
4224  *          point, for more points getCellsContainingPoints() is recommended as it is
4225  *          faster. 
4226  *  \param [in] pos - array of coordinates of the ball central point.
4227  *  \param [in] eps - ball radius.
4228  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4229  *         if there are no such cells.
4230  *  \throw If the coordinates array is not set.
4231  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4232  */
4233 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4234 {
4235   std::vector<int> elts;
4236   getCellsContainingPoint(pos,eps,elts);
4237   if(elts.empty())
4238     return -1;
4239   return elts.front();
4240 }
4241
4242 /*!
4243  * Finds cells in contact with a ball (i.e. a point with precision).
4244  * 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.
4245  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4246  * \warning This method is suitable if the caller intends to evaluate only one
4247  *          point, for more points getCellsContainingPoints() is recommended as it is
4248  *          faster. 
4249  *  \param [in] pos - array of coordinates of the ball central point.
4250  *  \param [in] eps - ball radius.
4251  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4252  *         before inserting ids.
4253  *  \throw If the coordinates array is not set.
4254  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4255  *
4256  *  \if ENABLE_EXAMPLES
4257  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4258  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4259  *  \endif
4260  */
4261 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4262 {
4263   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4264   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4265   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4266 }
4267
4268 /// @cond INTERNAL
4269
4270 namespace ParaMEDMEM
4271 {
4272   template<const int SPACEDIMM>
4273   class DummyClsMCUG
4274   {
4275   public:
4276     static const int MY_SPACEDIM=SPACEDIMM;
4277     static const int MY_MESHDIM=8;
4278     typedef int MyConnType;
4279     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4280     // begin
4281     // useless, but for windows compilation ...
4282     const double* getCoordinatesPtr() const { return 0; }
4283     const int* getConnectivityPtr() const { return 0; }
4284     const int* getConnectivityIndexPtr() const { return 0; }
4285     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4286     // end
4287   };
4288
4289   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4290   {
4291     INTERP_KERNEL::Edge *ret(0);
4292     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]));
4293     m[n0]=bg[0]; m[n1]=bg[1];
4294     switch(typ)
4295     {
4296       case INTERP_KERNEL::NORM_SEG2:
4297         {
4298           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4299           break;
4300         }
4301       case INTERP_KERNEL::NORM_SEG3:
4302         {
4303           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4304           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4305           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4306           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4307           bool colinearity(inters.areColinears());
4308           delete e1; delete e2;
4309           if(colinearity)
4310             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4311           else
4312             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4313           break;
4314         }
4315       default:
4316         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4317     }
4318     return ret;
4319   }
4320
4321   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4322   {
4323     INTERP_KERNEL::Edge *ret=0;
4324     switch(typ)
4325     {
4326       case INTERP_KERNEL::NORM_SEG2:
4327         {
4328           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4329           break;
4330         }
4331       case INTERP_KERNEL::NORM_SEG3:
4332         {
4333           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4334           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4335           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4336           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4337           bool colinearity=inters.areColinears();
4338           delete e1; delete e2;
4339           if(colinearity)
4340             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4341           else
4342             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4343           mapp2[bg[2]].second=false;
4344           break;
4345         }
4346       default:
4347         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4348     }
4349     return ret;
4350   }
4351
4352   /*!
4353    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4354    * the global mesh 'mDesc'.
4355    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4356    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4357    */
4358   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4359                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4360   {
4361     mapp.clear();
4362     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.
4363     const double *coo=mDesc->getCoords()->getConstPointer();
4364     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4365     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4366     std::set<int> s;
4367     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4368       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4369     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4370       {
4371         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4372         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4373       }
4374     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4375     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4376       {
4377         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4378         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4379       }
4380     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4381       {
4382         if((*it2).second.second)
4383           mapp[(*it2).second.first]=(*it2).first;
4384         ((*it2).second.first)->decrRef();
4385       }
4386     return ret;
4387   }
4388
4389   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4390   {
4391     if(nodeId>=offset2)
4392       {
4393         int locId=nodeId-offset2;
4394         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4395       }
4396     if(nodeId>=offset1)
4397       {
4398         int locId=nodeId-offset1;
4399         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4400       }
4401     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4402   }
4403
4404   /**
4405    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4406    */
4407   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4408                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4409                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4410   {
4411     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4412       {
4413         int eltId1=abs(*desc1)-1;
4414         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4415           {
4416             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4417             if(it==mappRev.end())
4418               {
4419                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4420                 mapp[node]=*it1;
4421                 mappRev[*it1]=node;
4422               }
4423           }
4424       }
4425   }
4426 }
4427
4428 /// @endcond
4429
4430 template<int SPACEDIM>
4431 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4432                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4433 {
4434   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4435   int *eltsIndexPtr(eltsIndex->getPointer());
4436   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4437   const double *bbox(bboxArr->begin());
4438   int nbOfCells=getNumberOfCells();
4439   const int *conn=_nodal_connec->getConstPointer();
4440   const int *connI=_nodal_connec_index->getConstPointer();
4441   double bb[2*SPACEDIM];
4442   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4443   for(int i=0;i<nbOfPoints;i++)
4444     {
4445       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4446       for(int j=0;j<SPACEDIM;j++)
4447         {
4448           bb[2*j]=pos[SPACEDIM*i+j];
4449           bb[2*j+1]=pos[SPACEDIM*i+j];
4450         }
4451       std::vector<int> candidates;
4452       myTree.getIntersectingElems(bb,candidates);
4453       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4454         {
4455           int sz(connI[(*iter)+1]-connI[*iter]-1);
4456           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4457           bool status(false);
4458           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4459             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4460           else
4461             {
4462               if(SPACEDIM!=2)
4463                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4464               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4465               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4466               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4467               INTERP_KERNEL::QuadraticPolygon *pol(0);
4468               for(int j=0;j<sz;j++)
4469                 {
4470                   int nodeId(conn[connI[*iter]+1+j]);
4471                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4472                 }
4473               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4474                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4475               else
4476                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4477               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4478               double a(0.),b(0.),c(0.);
4479               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4480               status=pol->isInOrOut2(n);
4481               delete pol; n->decrRef();
4482             }
4483           if(status)
4484             {
4485               eltsIndexPtr[i+1]++;
4486               elts->pushBackSilent(*iter);
4487             }
4488         }
4489     }
4490 }
4491 /*!
4492  * Finds cells in contact with several balls (i.e. points with precision).
4493  * This method is an extension of getCellContainingPoint() and
4494  * getCellsContainingPoint() for the case of multiple points.
4495  * 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.
4496  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4497  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4498  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4499  *         this->getSpaceDimension() * \a nbOfPoints 
4500  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4501  *  \param [in] eps - radius of balls (i.e. the precision).
4502  *  \param [out] elts - vector returning ids of found cells.
4503  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4504  *         dividing cell ids in \a elts into groups each referring to one
4505  *         point. Its every element (except the last one) is an index pointing to the
4506  *         first id of a group of cells. For example cells in contact with the *i*-th
4507  *         point are described by following range of indices:
4508  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4509  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4510  *         Number of cells in contact with the *i*-th point is
4511  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4512  *  \throw If the coordinates array is not set.
4513  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4514  *
4515  *  \if ENABLE_EXAMPLES
4516  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4517  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4518  *  \endif
4519  */
4520 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4521                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4522 {
4523   int spaceDim=getSpaceDimension();
4524   int mDim=getMeshDimension();
4525   if(spaceDim==3)
4526     {
4527       if(mDim==3)
4528         {
4529           const double *coords=_coords->getConstPointer();
4530           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4531         }
4532       /*else if(mDim==2)
4533         {
4534
4535         }*/
4536       else
4537         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4538     }
4539   else if(spaceDim==2)
4540     {
4541       if(mDim==2)
4542         {
4543           const double *coords=_coords->getConstPointer();
4544           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4545         }
4546       else
4547         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4548     }
4549   else if(spaceDim==1)
4550     {
4551       if(mDim==1)
4552         {
4553           const double *coords=_coords->getConstPointer();
4554           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4555         }
4556       else
4557         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4558     }
4559   else
4560     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4561 }
4562
4563 /*!
4564  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4565  * least two its edges intersect each other anywhere except their extremities. An
4566  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4567  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4568  *         cleared before filling in.
4569  *  \param [in] eps - precision.
4570  *  \throw If \a this->getMeshDimension() != 2.
4571  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4572  */
4573 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4574 {
4575   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4576   if(getMeshDimension()!=2)
4577     throw INTERP_KERNEL::Exception(msg);
4578   int spaceDim=getSpaceDimension();
4579   if(spaceDim!=2 && spaceDim!=3)
4580     throw INTERP_KERNEL::Exception(msg);
4581   const int *conn=_nodal_connec->getConstPointer();
4582   const int *connI=_nodal_connec_index->getConstPointer();
4583   int nbOfCells=getNumberOfCells();
4584   std::vector<double> cell2DinS2;
4585   for(int i=0;i<nbOfCells;i++)
4586     {
4587       int offset=connI[i];
4588       int nbOfNodesForCell=connI[i+1]-offset-1;
4589       if(nbOfNodesForCell<=3)
4590         continue;
4591       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4592       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4593       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4594         cells.push_back(i);
4595       cell2DinS2.clear();
4596     }
4597 }
4598
4599 /*!
4600  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4601  *
4602  * 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.
4603  * 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.
4604  * 
4605  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4606  * This convex envelop is computed using Jarvis march algorithm.
4607  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4608  * 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)
4609  * 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.
4610  *
4611  * \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.
4612  * \sa MEDCouplingUMesh::colinearize2D
4613  */
4614 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4615 {
4616   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4617     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4618   checkFullyDefined();
4619   const double *coords=getCoords()->getConstPointer();
4620   int nbOfCells=getNumberOfCells();
4621   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4622   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4623   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4624   int *workIndexOut=nodalConnecIndexOut->getPointer();
4625   *workIndexOut=0;
4626   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4627   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4628   std::set<INTERP_KERNEL::NormalizedCellType> types;
4629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4630   isChanged->alloc(0,1);
4631   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4632     {
4633       int pos=nodalConnecOut->getNumberOfTuples();
4634       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4635         isChanged->pushBackSilent(i);
4636       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4637       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4638     }
4639   if(isChanged->empty())
4640     return 0;
4641   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4642   _types=types;
4643   return isChanged.retn();
4644 }
4645
4646 /*!
4647  * This method is \b NOT const because it can modify \a this.
4648  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4649  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4650  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4651  * \b 1 for translation and rotation around point of 'mesh1D'.
4652  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4653  */
4654 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4655 {
4656   checkFullyDefined();
4657   mesh1D->checkFullyDefined();
4658   if(!mesh1D->isContiguous1D())
4659     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4660   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4661     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4662   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4663     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4664   if(mesh1D->getMeshDimension()!=1)
4665     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4666   bool isQuad=false;
4667   if(isPresenceOfQuadratic())
4668     {
4669       if(mesh1D->isFullyQuadratic())
4670         isQuad=true;
4671       else
4672         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4673     }
4674   int oldNbOfNodes(getNumberOfNodes());
4675   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4676   switch(policy)
4677   {
4678     case 0:
4679       {
4680         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4681         break;
4682       }
4683     case 1:
4684       {
4685         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4686         break;
4687       }
4688     default:
4689       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4690   }
4691   setCoords(newCoords);
4692   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4693   updateTime();
4694   return ret.retn();
4695 }
4696
4697 /*!
4698  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4699  * If it is not the case an exception will be thrown.
4700  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4701  * intersection of plane defined by ('origin','vec').
4702  * This method has one in/out parameter : 'cut3DCurve'.
4703  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4704  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4705  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4706  * This method will throw an exception if \a this contains a non linear segment.
4707  */
4708 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4709 {
4710   checkFullyDefined();
4711   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4712     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4713   int ncells=getNumberOfCells();
4714   int nnodes=getNumberOfNodes();
4715   double vec2[3],vec3[3],vec4[3];
4716   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4717   if(normm<1e-6)
4718     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4719   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4720   const int *conn=_nodal_connec->getConstPointer();
4721   const int *connI=_nodal_connec_index->getConstPointer();
4722   const double *coo=_coords->getConstPointer();
4723   std::vector<double> addCoo;
4724   for(int i=0;i<ncells;i++)
4725     {
4726       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4727         {
4728           if(cut3DCurve[i]==-2)
4729             {
4730               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4731               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];
4732               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4733               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4734               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4735                 {
4736                   const double *st2=coo+3*st;
4737                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4738                   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]));
4739                   if(pos>eps && pos<1-eps)
4740                     {
4741                       int nNode=((int)addCoo.size())/3;
4742                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4743                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4744                       cut3DCurve[i]=nnodes+nNode;
4745                     }
4746                 }
4747             }
4748         }
4749       else
4750         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4751     }
4752   if(!addCoo.empty())
4753     {
4754       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4755       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4756       coo2->alloc(newNbOfNodes,3);
4757       double *tmp=coo2->getPointer();
4758       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4759       std::copy(addCoo.begin(),addCoo.end(),tmp);
4760       DataArrayDouble::SetArrayIn(coo2,_coords);
4761     }
4762 }
4763
4764 /*!
4765  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4766  * \param mesh1D is the input 1D mesh used for translation computation.
4767  * \return newCoords new coords filled by this method. 
4768  */
4769 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4770 {
4771   int oldNbOfNodes=getNumberOfNodes();
4772   int nbOf1DCells=mesh1D->getNumberOfCells();
4773   int spaceDim=getSpaceDimension();
4774   DataArrayDouble *ret=DataArrayDouble::New();
4775   std::vector<bool> isQuads;
4776   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4777   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4778   double *retPtr=ret->getPointer();
4779   const double *coords=getCoords()->getConstPointer();
4780   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4781   std::vector<int> v;
4782   std::vector<double> c;
4783   double vec[3];
4784   v.reserve(3);
4785   c.reserve(6);
4786   for(int i=0;i<nbOf1DCells;i++)
4787     {
4788       v.resize(0);
4789       mesh1D->getNodeIdsOfCell(i,v);
4790       c.resize(0);
4791       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4792       mesh1D->getCoordinatesOfNode(v[0],c);
4793       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4794       for(int j=0;j<oldNbOfNodes;j++)
4795         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4796       if(isQuad)
4797         {
4798           c.resize(0);
4799           mesh1D->getCoordinatesOfNode(v[1],c);
4800           mesh1D->getCoordinatesOfNode(v[0],c);
4801           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4802           for(int j=0;j<oldNbOfNodes;j++)
4803             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4804         }
4805     }
4806   ret->copyStringInfoFrom(*getCoords());
4807   return ret;
4808 }
4809
4810 /*!
4811  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4812  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4813  * \return newCoords new coords filled by this method. 
4814  */
4815 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4816 {
4817   if(mesh1D->getSpaceDimension()==2)
4818     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4819   if(mesh1D->getSpaceDimension()==3)
4820     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4821   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4822 }
4823
4824 /*!
4825  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4826  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4827  * \return newCoords new coords filled by this method. 
4828  */
4829 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4830 {
4831   if(isQuad)
4832     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4833   int oldNbOfNodes=getNumberOfNodes();
4834   int nbOf1DCells=mesh1D->getNumberOfCells();
4835   if(nbOf1DCells<2)
4836     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4837   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4838   int nbOfLevsInVec=nbOf1DCells+1;
4839   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4840   double *retPtr=ret->getPointer();
4841   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4842   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4843   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4844   tmp->setCoords(tmp2);
4845   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4846   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4847   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4848   for(int i=1;i<nbOfLevsInVec;i++)
4849     {
4850       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4851       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4852       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4853       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4854       tmp->translate(vec);
4855       double tmp3[2],radius,alpha,alpha0;
4856       const double *p0=i+1<nbOfLevsInVec?begin:third;
4857       const double *p1=i+1<nbOfLevsInVec?end:begin;
4858       const double *p2=i+1<nbOfLevsInVec?third:end;
4859       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4860       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]);
4861       double angle=acos(cosangle/(radius*radius));
4862       tmp->rotate(end,0,angle);
4863       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4864     }
4865   return ret.retn();
4866 }
4867
4868 /*!
4869  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4870  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4871  * \return newCoords new coords filled by this method. 
4872  */
4873 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4874 {
4875   if(isQuad)
4876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4877   int oldNbOfNodes=getNumberOfNodes();
4878   int nbOf1DCells=mesh1D->getNumberOfCells();
4879   if(nbOf1DCells<2)
4880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4881   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4882   int nbOfLevsInVec=nbOf1DCells+1;
4883   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4884   double *retPtr=ret->getPointer();
4885   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4886   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4887   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4888   tmp->setCoords(tmp2);
4889   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4890   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4891   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4892   for(int i=1;i<nbOfLevsInVec;i++)
4893     {
4894       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4895       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4896       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4897       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4898       tmp->translate(vec);
4899       double tmp3[2],radius,alpha,alpha0;
4900       const double *p0=i+1<nbOfLevsInVec?begin:third;
4901       const double *p1=i+1<nbOfLevsInVec?end:begin;
4902       const double *p2=i+1<nbOfLevsInVec?third:end;
4903       double vecPlane[3]={
4904         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4905         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4906         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4907       };
4908       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4909       if(norm>1.e-7)
4910         {
4911           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4912           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4913           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4914           double s2=norm2;
4915           double c2=cos(asin(s2));
4916           double m[3][3]={
4917             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4918             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4919             {-vec2[1]*s2, vec2[0]*s2, c2}
4920           };
4921           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]};
4922           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]};
4923           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]};
4924           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4925           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]);
4926           double angle=acos(cosangle/(radius*radius));
4927           tmp->rotate(end,vecPlane,angle);
4928         }
4929       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4930     }
4931   return ret.retn();
4932 }
4933
4934 /*!
4935  * This method is private because not easy to use for end user. This method is const contrary to
4936  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4937  * the coords sorted slice by slice.
4938  * \param isQuad specifies presence of quadratic cells.
4939  */
4940 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4941 {
4942   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4943   int nbOf2DCells(getNumberOfCells());
4944   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4945   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4946   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4947   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4948   newConnI->alloc(nbOf3DCells+1,1);
4949   int *newConnIPtr(newConnI->getPointer());
4950   *newConnIPtr++=0;
4951   std::vector<int> newc;
4952   for(int j=0;j<nbOf2DCells;j++)
4953     {
4954       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4955       *newConnIPtr++=(int)newc.size();
4956     }
4957   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4958   int *newConnPtr(newConn->getPointer());
4959   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4960   newConnIPtr=newConnI->getPointer();
4961   for(int iz=0;iz<nbOf1DCells;iz++)
4962     {
4963       if(iz!=0)
4964         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4965       const int *posOfTypeOfCell(newConnIPtr);
4966       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4967         {
4968           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4969           if(icell!=*posOfTypeOfCell)
4970             {
4971               if(*iter!=-1)
4972                 *newConnPtr=(*iter)+iz*deltaPerLev;
4973               else
4974                 *newConnPtr=-1;
4975             }
4976           else
4977             {
4978               *newConnPtr=*iter;
4979               posOfTypeOfCell++;
4980             }
4981         }
4982     }
4983   ret->setConnectivity(newConn,newConnI,true);
4984   ret->setCoords(getCoords());
4985   return ret;
4986 }
4987
4988 /*!
4989  * Checks if \a this mesh is constituted by only quadratic cells.
4990  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4991  *  \throw If the coordinates array is not set.
4992  *  \throw If the nodal connectivity of cells is not defined.
4993  */
4994 bool MEDCouplingUMesh::isFullyQuadratic() const
4995 {
4996   checkFullyDefined();
4997   bool ret=true;
4998   int nbOfCells=getNumberOfCells();
4999   for(int i=0;i<nbOfCells && ret;i++)
5000     {
5001       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5002       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5003       ret=cm.isQuadratic();
5004     }
5005   return ret;
5006 }
5007
5008 /*!
5009  * Checks if \a this mesh includes any quadratic cell.
5010  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5011  *  \throw If the coordinates array is not set.
5012  *  \throw If the nodal connectivity of cells is not defined.
5013  */
5014 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5015 {
5016   checkFullyDefined();
5017   bool ret=false;
5018   int nbOfCells=getNumberOfCells();
5019   for(int i=0;i<nbOfCells && !ret;i++)
5020     {
5021       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5022       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5023       ret=cm.isQuadratic();
5024     }
5025   return ret;
5026 }
5027
5028 /*!
5029  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5030  * this mesh, it remains unchanged.
5031  *  \throw If the coordinates array is not set.
5032  *  \throw If the nodal connectivity of cells is not defined.
5033  */
5034 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5035 {
5036   checkFullyDefined();
5037   int nbOfCells=getNumberOfCells();
5038   int delta=0;
5039   const int *iciptr=_nodal_connec_index->getConstPointer();
5040   for(int i=0;i<nbOfCells;i++)
5041     {
5042       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5043       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5044       if(cm.isQuadratic())
5045         {
5046           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5047           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5048           if(!cml.isDynamic())
5049             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5050           else
5051             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5052         }
5053     }
5054   if(delta==0)
5055     return ;
5056   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5057   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5058   const int *icptr=_nodal_connec->getConstPointer();
5059   newConn->alloc(getMeshLength()-delta,1);
5060   newConnI->alloc(nbOfCells+1,1);
5061   int *ocptr=newConn->getPointer();
5062   int *ociptr=newConnI->getPointer();
5063   *ociptr=0;
5064   _types.clear();
5065   for(int i=0;i<nbOfCells;i++,ociptr++)
5066     {
5067       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5068       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5069       if(!cm.isQuadratic())
5070         {
5071           _types.insert(type);
5072           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5073           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5074         }
5075       else
5076         {
5077           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5078           _types.insert(typel);
5079           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5080           int newNbOfNodes=cml.getNumberOfNodes();
5081           if(cml.isDynamic())
5082             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5083           *ocptr++=(int)typel;
5084           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5085           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5086         }
5087     }
5088   setConnectivity(newConn,newConnI,false);
5089 }
5090
5091 /*!
5092  * This method converts all linear cell in \a this to quadratic one.
5093  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5094  * 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)
5095  * 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.
5096  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5097  * end of the existing coordinates.
5098  * 
5099  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5100  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5101  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5102  * 
5103  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5104  *
5105  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5106  */
5107 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5108 {
5109   DataArrayInt *conn=0,*connI=0;
5110   DataArrayDouble *coords=0;
5111   std::set<INTERP_KERNEL::NormalizedCellType> types;
5112   checkFullyDefined();
5113   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5114   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5115   int meshDim=getMeshDimension();
5116   switch(conversionType)
5117   {
5118     case 0:
5119       switch(meshDim)
5120       {
5121         case 1:
5122           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5123           connSafe=conn; connISafe=connI; coordsSafe=coords;
5124           break;
5125         case 2:
5126           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5127           connSafe=conn; connISafe=connI; coordsSafe=coords;
5128           break;
5129         case 3:
5130           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5131           connSafe=conn; connISafe=connI; coordsSafe=coords;
5132           break;
5133         default:
5134           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5135       }
5136       break;
5137         case 1:
5138           {
5139             switch(meshDim)
5140             {
5141               case 1:
5142                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5143                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5144                 break;
5145               case 2:
5146                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5147                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5148                 break;
5149               case 3:
5150                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5151                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5152                 break;
5153               default:
5154                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5155             }
5156             break;
5157           }
5158         default:
5159           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5160   }
5161   setConnectivity(connSafe,connISafe,false);
5162   _types=types;
5163   setCoords(coordsSafe);
5164   return ret.retn();
5165 }
5166
5167 #if 0
5168 /*!
5169  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5170  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5171  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5172  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5173  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5174  * This method can be seen as the opposite method of colinearize2D.
5175  * 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
5176  * to avoid to modify the numbering of existing nodes.
5177  *
5178  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5179  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5180  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5181  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5182  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5183  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5184  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5185  *
5186  * \sa buildDescendingConnectivity2
5187  */
5188 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5189                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5190 {
5191   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5192     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5193   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5194   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5195     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5196   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5197     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5198   //DataArrayInt *out0(0),*outi0(0);
5199   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5200   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5201   //out0s=out0s->buildUnique(); out0s->sort(true);
5202 }
5203 #endif
5204
5205 /*!
5206  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5207  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5208  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5209  */
5210 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5211 {
5212   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5214   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5215   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5216   int nbOfCells=getNumberOfCells();
5217   int nbOfNodes=getNumberOfNodes();
5218   const int *cPtr=_nodal_connec->getConstPointer();
5219   const int *icPtr=_nodal_connec_index->getConstPointer();
5220   int lastVal=0,offset=nbOfNodes;
5221   for(int i=0;i<nbOfCells;i++,icPtr++)
5222     {
5223       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5224       if(type==INTERP_KERNEL::NORM_SEG2)
5225         {
5226           types.insert(INTERP_KERNEL::NORM_SEG3);
5227           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5228           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5229           newConn->pushBackSilent(offset++);
5230           lastVal+=4;
5231           newConnI->pushBackSilent(lastVal);
5232           ret->pushBackSilent(i);
5233         }
5234       else
5235         {
5236           types.insert(type);
5237           lastVal+=(icPtr[1]-icPtr[0]);
5238           newConnI->pushBackSilent(lastVal);
5239           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5240         }
5241     }
5242   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5243   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5244   return ret.retn();
5245 }
5246
5247 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
5248 {
5249   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5252   //
5253   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5254   DataArrayInt *conn1D=0,*conn1DI=0;
5255   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5256   DataArrayDouble *coordsTmp=0;
5257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5258   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5260   const int *c1DPtr=conn1D->begin();
5261   const int *c1DIPtr=conn1DI->begin();
5262   int nbOfCells=getNumberOfCells();
5263   const int *cPtr=_nodal_connec->getConstPointer();
5264   const int *icPtr=_nodal_connec_index->getConstPointer();
5265   int lastVal=0;
5266   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5267     {
5268       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5269       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5270       if(!cm.isQuadratic())
5271         {
5272           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5273           types.insert(typ2); newConn->pushBackSilent(typ2);
5274           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5275           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5276             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5277           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5278           newConnI->pushBackSilent(lastVal);
5279           ret->pushBackSilent(i);
5280         }
5281       else
5282         {
5283           types.insert(typ);
5284           lastVal+=(icPtr[1]-icPtr[0]);
5285           newConnI->pushBackSilent(lastVal);
5286           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5287         }
5288     }
5289   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5290   return ret.retn();
5291 }
5292
5293 /*!
5294  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5295  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5296  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5297  */
5298 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5299 {
5300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5301   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5302   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5303 }
5304
5305 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5306 {
5307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5308   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5309   //
5310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5312   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5313   //
5314   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5315   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5316   DataArrayInt *conn1D=0,*conn1DI=0;
5317   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5318   DataArrayDouble *coordsTmp=0;
5319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5320   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5322   const int *c1DPtr=conn1D->begin();
5323   const int *c1DIPtr=conn1DI->begin();
5324   int nbOfCells=getNumberOfCells();
5325   const int *cPtr=_nodal_connec->getConstPointer();
5326   const int *icPtr=_nodal_connec_index->getConstPointer();
5327   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5328   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5329     {
5330       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5331       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5332       if(!cm.isQuadratic())
5333         {
5334           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5335           types.insert(typ2); newConn->pushBackSilent(typ2);
5336           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5337           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5338             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5339           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5340           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5341           newConnI->pushBackSilent(lastVal);
5342           ret->pushBackSilent(i);
5343         }
5344       else
5345         {
5346           types.insert(typ);
5347           lastVal+=(icPtr[1]-icPtr[0]);
5348           newConnI->pushBackSilent(lastVal);
5349           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5350         }
5351     }
5352   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5353   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5354   return ret.retn();
5355 }
5356
5357 /*!
5358  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5359  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5360  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5361  */
5362 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5363 {
5364   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5365   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5366   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5367 }
5368
5369 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5370 {
5371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5372   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5374   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5375   //
5376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5379   //
5380   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5381   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5382   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5383   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5384   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5387   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5389   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5391   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5392   int nbOfCells=getNumberOfCells();
5393   const int *cPtr=_nodal_connec->getConstPointer();
5394   const int *icPtr=_nodal_connec_index->getConstPointer();
5395   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5396   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5397     {
5398       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5399       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5400       if(!cm.isQuadratic())
5401         {
5402           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5403           if(typ2==INTERP_KERNEL::NORM_ERROR)
5404             {
5405               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5406               throw INTERP_KERNEL::Exception(oss.str().c_str());
5407             }
5408           types.insert(typ2); newConn->pushBackSilent(typ2);
5409           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5410           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5411             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5412           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5413             {
5414               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5415               int tmpPos=newConn->getNumberOfTuples();
5416               newConn->pushBackSilent(nodeId2);
5417               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5418             }
5419           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5420           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5421           newConnI->pushBackSilent(lastVal);
5422           ret->pushBackSilent(i);
5423         }
5424       else
5425         {
5426           types.insert(typ);
5427           lastVal+=(icPtr[1]-icPtr[0]);
5428           newConnI->pushBackSilent(lastVal);
5429           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5430         }
5431     }
5432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5434   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5435   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5436   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5437   int *c=newConn->getPointer();
5438   const int *cI(newConnI->begin());
5439   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5440     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5441   offset=coordsTmp2Safe->getNumberOfTuples();
5442   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5443     c[cI[(*elt)+1]-1]+=offset;
5444   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5445   return ret.retn();
5446 }
5447
5448 /*!
5449  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5450  * so that the number of cells remains the same. Quadratic faces are converted to
5451  * polygons. This method works only for 2D meshes in
5452  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5453  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5454  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5455  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5456  *         a polylinized edge constituting the input polygon.
5457  *  \throw If the coordinates array is not set.
5458  *  \throw If the nodal connectivity of cells is not defined.
5459  *  \throw If \a this->getMeshDimension() != 2.
5460  *  \throw If \a this->getSpaceDimension() != 2.
5461  */
5462 void MEDCouplingUMesh::tessellate2D(double eps)
5463 {
5464   checkFullyDefined();
5465   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5467   double epsa=fabs(eps);
5468   if(epsa<std::numeric_limits<double>::min())
5469     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 !");
5470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5473   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5474   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5475   revDesc1=0; revDescIndx1=0;
5476   mDesc->tessellate2DCurve(eps);
5477   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5478   setCoords(mDesc->getCoords());
5479 }
5480
5481 /*!
5482  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5483  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5484  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5485  *         a sub-divided edge.
5486  *  \throw If the coordinates array is not set.
5487  *  \throw If the nodal connectivity of cells is not defined.
5488  *  \throw If \a this->getMeshDimension() != 1.
5489  *  \throw If \a this->getSpaceDimension() != 2.
5490  */
5491 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5492 {
5493   checkFullyDefined();
5494   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5495     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5496   double epsa=fabs(eps);
5497   if(epsa<std::numeric_limits<double>::min())
5498     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 !");
5499   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5500   int nbCells=getNumberOfCells();
5501   int nbNodes=getNumberOfNodes();
5502   const int *conn=_nodal_connec->getConstPointer();
5503   const int *connI=_nodal_connec_index->getConstPointer();
5504   const double *coords=_coords->getConstPointer();
5505   std::vector<double> addCoo;
5506   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5507   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5508   newConnI->alloc(nbCells+1,1);
5509   int *newConnIPtr=newConnI->getPointer();
5510   *newConnIPtr=0;
5511   int tmp1[3];
5512   INTERP_KERNEL::Node *tmp2[3];
5513   std::set<INTERP_KERNEL::NormalizedCellType> types;
5514   for(int i=0;i<nbCells;i++,newConnIPtr++)
5515     {
5516       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5517       if(cm.isQuadratic())
5518         {//assert(connI[i+1]-connI[i]-1==3)
5519           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5520           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5521           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5522           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5523           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5524           if(eac)
5525             {
5526               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5527               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5528               delete eac;
5529               newConnIPtr[1]=(int)newConn.size();
5530             }
5531           else
5532             {
5533               types.insert(INTERP_KERNEL::NORM_SEG2);
5534               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5535               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5536               newConnIPtr[1]=newConnIPtr[0]+3;
5537             }
5538         }
5539       else
5540         {
5541           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5542           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5543           newConnIPtr[1]=newConnIPtr[0]+3;
5544         }
5545     }
5546   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5547     return ;
5548   _types=types;
5549   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5550   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5551   newConnArr->alloc((int)newConn.size(),1);
5552   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5553   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5554   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5555   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5556   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5557   std::copy(addCoo.begin(),addCoo.end(),work);
5558   DataArrayDouble::SetArrayIn(newCoords,_coords);
5559   updateTime();
5560 }
5561
5562 /*!
5563  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5564  * In addition, returns an array mapping new cells to old ones. <br>
5565  * This method typically increases the number of cells in \a this mesh
5566  * but the number of nodes remains \b unchanged.
5567  * That's why the 3D splitting policies
5568  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5569  *  \param [in] policy - specifies a pattern used for splitting.
5570  * The semantic of \a policy is:
5571  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5572  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5573  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5574  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5575  *
5576  *
5577  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5578  *          an id of old cell producing it. The caller is to delete this array using
5579  *         decrRef() as it is no more needed.
5580  *
5581  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5582  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5583  *          and \a this->getMeshDimension() != 3. 
5584  *  \throw If \a policy is not one of the four discussed above.
5585  *  \throw If the nodal connectivity of cells is not defined.
5586  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5587  */
5588 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5589 {
5590   switch(policy)
5591   {
5592     case 0:
5593       return simplexizePol0();
5594     case 1:
5595       return simplexizePol1();
5596     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5597         return simplexizePlanarFace5();
5598     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5599         return simplexizePlanarFace6();
5600     default:
5601       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)");
5602   }
5603 }
5604
5605 /*!
5606  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5607  * - 1D: INTERP_KERNEL::NORM_SEG2
5608  * - 2D: INTERP_KERNEL::NORM_TRI3
5609  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5610  *
5611  * This method is useful for users that need to use P1 field services as
5612  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5613  * All these methods need mesh support containing only simplex cells.
5614  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5615  *  \throw If the coordinates array is not set.
5616  *  \throw If the nodal connectivity of cells is not defined.
5617  *  \throw If \a this->getMeshDimension() < 1.
5618  */
5619 bool MEDCouplingUMesh::areOnlySimplexCells() const
5620 {
5621   checkFullyDefined();
5622   int mdim=getMeshDimension();
5623   if(mdim<1 || mdim>3)
5624     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5625   int nbCells=getNumberOfCells();
5626   const int *conn=_nodal_connec->getConstPointer();
5627   const int *connI=_nodal_connec_index->getConstPointer();
5628   for(int i=0;i<nbCells;i++)
5629     {
5630       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5631       if(!cm.isSimplex())
5632         return false;
5633     }
5634   return true;
5635 }
5636
5637 /*!
5638  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5639  */
5640 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
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]+3],
5665             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],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 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5692  */
5693 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5694 {
5695   checkConnectivityFullyDefined();
5696   if(getMeshDimension()!=2)
5697     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5698   int nbOfCells=getNumberOfCells();
5699   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5700   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5701   ret->alloc(nbOfCells+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+nbOfCutCells+1,1);
5707   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
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_QUAD4)
5716         {
5717           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5718             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5719           pt=std::copy(tmp,tmp+8,pt);
5720           ptI[1]=ptI[0]+4;
5721           ptI[2]=ptI[0]+8;
5722           *retPt++=i;
5723           *retPt++=i;
5724           ptI+=2;
5725         }
5726       else
5727         {
5728           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5729           ptI[1]=ptI[0]+ci[1]-ci[0];
5730           ptI++;
5731           *retPt++=i;
5732         }
5733     }
5734   _nodal_connec->decrRef();
5735   _nodal_connec=newConn.retn();
5736   _nodal_connec_index->decrRef();
5737   _nodal_connec_index=newConnI.retn();
5738   computeTypes();
5739   updateTime();
5740   return ret.retn();
5741 }
5742
5743 /*!
5744  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5745  */
5746 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5747 {
5748   checkConnectivityFullyDefined();
5749   if(getMeshDimension()!=3)
5750     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5751   int nbOfCells=getNumberOfCells();
5752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5753   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5754   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5755   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5756   int *retPt=ret->getPointer();
5757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5759   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5760   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5761   int *pt=newConn->getPointer();
5762   int *ptI=newConnI->getPointer();
5763   ptI[0]=0;
5764   const int *oldc=_nodal_connec->getConstPointer();
5765   const int *ci=_nodal_connec_index->getConstPointer();
5766   for(int i=0;i<nbOfCells;i++,ci++)
5767     {
5768       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5769         {
5770           for(int j=0;j<5;j++,pt+=5,ptI++)
5771             {
5772               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5773               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];
5774               *retPt++=i;
5775               ptI[1]=ptI[0]+5;
5776             }
5777         }
5778       else
5779         {
5780           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5781           ptI[1]=ptI[0]+ci[1]-ci[0];
5782           ptI++;
5783           *retPt++=i;
5784         }
5785     }
5786   _nodal_connec->decrRef();
5787   _nodal_connec=newConn.retn();
5788   _nodal_connec_index->decrRef();
5789   _nodal_connec_index=newConnI.retn();
5790   computeTypes();
5791   updateTime();
5792   return ret.retn();
5793 }
5794
5795 /*!
5796  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5797  */
5798 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5799 {
5800   checkConnectivityFullyDefined();
5801   if(getMeshDimension()!=3)
5802     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5803   int nbOfCells=getNumberOfCells();
5804   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5805   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5806   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5807   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5808   int *retPt=ret->getPointer();
5809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5811   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5812   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5813   int *pt=newConn->getPointer();
5814   int *ptI=newConnI->getPointer();
5815   ptI[0]=0;
5816   const int *oldc=_nodal_connec->getConstPointer();
5817   const int *ci=_nodal_connec_index->getConstPointer();
5818   for(int i=0;i<nbOfCells;i++,ci++)
5819     {
5820       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5821         {
5822           for(int j=0;j<6;j++,pt+=5,ptI++)
5823             {
5824               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5825               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];
5826               *retPt++=i;
5827               ptI[1]=ptI[0]+5;
5828             }
5829         }
5830       else
5831         {
5832           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5833           ptI[1]=ptI[0]+ci[1]-ci[0];
5834           ptI++;
5835           *retPt++=i;
5836         }
5837     }
5838   _nodal_connec->decrRef();
5839   _nodal_connec=newConn.retn();
5840   _nodal_connec_index->decrRef();
5841   _nodal_connec_index=newConnI.retn();
5842   computeTypes();
5843   updateTime();
5844   return ret.retn();
5845 }
5846
5847 /*!
5848  * 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.
5849  * This method completly ignore coordinates.
5850  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5851  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5852  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5853  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5854  */
5855 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5856 {
5857   checkFullyDefined();
5858   if(getMeshDimension()!=2)
5859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5860   int nbOfCells=getNumberOfCells();
5861   int *connI=_nodal_connec_index->getPointer();
5862   int newConnLgth=0;
5863   for(int i=0;i<nbOfCells;i++,connI++)
5864     {
5865       int offset=descIndex[i];
5866       int nbOfEdges=descIndex[i+1]-offset;
5867       //
5868       bool ddirect=desc[offset+nbOfEdges-1]>0;
5869       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5870       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5871       for(int j=0;j<nbOfEdges;j++)
5872         {
5873           bool direct=desc[offset+j]>0;
5874           int edgeId=std::abs(desc[offset+j])-1;
5875           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5876             {
5877               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5878               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5879               int ref2=direct?id1:id2;
5880               if(ref==ref2)
5881                 {
5882                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5883                   newConnLgth+=nbOfSubNodes-1;
5884                   ref=direct?id2:id1;
5885                 }
5886               else
5887                 {
5888                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5889                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5890                 }
5891             }
5892           else
5893             {
5894               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5895             }
5896         }
5897       newConnLgth++;//+1 is for cell type
5898       connI[1]=newConnLgth;
5899     }
5900   //
5901   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5902   newConn->alloc(newConnLgth,1);
5903   int *work=newConn->getPointer();
5904   for(int i=0;i<nbOfCells;i++)
5905     {
5906       *work++=INTERP_KERNEL::NORM_POLYGON;
5907       int offset=descIndex[i];
5908       int nbOfEdges=descIndex[i+1]-offset;
5909       for(int j=0;j<nbOfEdges;j++)
5910         {
5911           bool direct=desc[offset+j]>0;
5912           int edgeId=std::abs(desc[offset+j])-1;
5913           if(direct)
5914             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5915           else
5916             {
5917               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5918               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5919               work=std::copy(it,it+nbOfSubNodes-1,work);
5920             }
5921         }
5922     }
5923   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5924   _types.clear();
5925   if(nbOfCells>0)
5926     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5927 }
5928
5929 /*!
5930  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5931  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5932  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5933  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5934  * so it can be useful to call mergeNodes() before calling this method.
5935  *  \throw If \a this->getMeshDimension() <= 1.
5936  *  \throw If the coordinates array is not set.
5937  *  \throw If the nodal connectivity of cells is not defined.
5938  */
5939 void MEDCouplingUMesh::convertDegeneratedCells()
5940 {
5941   checkFullyDefined();
5942   if(getMeshDimension()<=1)
5943     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5944   int nbOfCells=getNumberOfCells();
5945   if(nbOfCells<1)
5946     return ;
5947   int initMeshLgth=getMeshLength();
5948   int *conn=_nodal_connec->getPointer();
5949   int *index=_nodal_connec_index->getPointer();
5950   int posOfCurCell=0;
5951   int newPos=0;
5952   int lgthOfCurCell;
5953   for(int i=0;i<nbOfCells;i++)
5954     {
5955       lgthOfCurCell=index[i+1]-posOfCurCell;
5956       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5957       int newLgth;
5958       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5959                                                                                                      conn+newPos+1,newLgth);
5960       conn[newPos]=newType;
5961       newPos+=newLgth+1;
5962       posOfCurCell=index[i+1];
5963       index[i+1]=newPos;
5964     }
5965   if(newPos!=initMeshLgth)
5966     _nodal_connec->reAlloc(newPos);
5967   computeTypes();
5968 }
5969
5970 /*!
5971  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5972  * A cell is considered to be oriented correctly if an angle between its
5973  * normal vector and a given vector is less than \c PI / \c 2.
5974  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5975  *         cells. 
5976  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5977  *         checked.
5978  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5979  *         is not cleared before filling in.
5980  *  \throw If \a this->getMeshDimension() != 2.
5981  *  \throw If \a this->getSpaceDimension() != 3.
5982  *
5983  *  \if ENABLE_EXAMPLES
5984  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5985  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5986  *  \endif
5987  */
5988 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5989 {
5990   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5991     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5992   int nbOfCells=getNumberOfCells();
5993   const int *conn=_nodal_connec->getConstPointer();
5994   const int *connI=_nodal_connec_index->getConstPointer();
5995   const double *coordsPtr=_coords->getConstPointer();
5996   for(int i=0;i<nbOfCells;i++)
5997     {
5998       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5999       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6000         {
6001           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6002           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6003             cells.push_back(i);
6004         }
6005     }
6006 }
6007
6008 /*!
6009  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6010  * considered to be oriented correctly if an angle between its normal vector and a
6011  * given vector is less than \c PI / \c 2. 
6012  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6013  *         cells. 
6014  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6015  *         checked.
6016  *  \throw If \a this->getMeshDimension() != 2.
6017  *  \throw If \a this->getSpaceDimension() != 3.
6018  *
6019  *  \if ENABLE_EXAMPLES
6020  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6021  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6022  *  \endif
6023  *
6024  *  \sa changeOrientationOfCells
6025  */
6026 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6027 {
6028   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6029     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6030   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6031   const int *connI(_nodal_connec_index->getConstPointer());
6032   const double *coordsPtr(_coords->getConstPointer());
6033   bool isModified(false);
6034   for(int i=0;i<nbOfCells;i++)
6035     {
6036       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6037       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6038         {
6039           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6040           bool isQuadratic(cm.isQuadratic());
6041           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6042             {
6043               isModified=true;
6044               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6045             }
6046         }
6047     }
6048   if(isModified)
6049     _nodal_connec->declareAsNew();
6050   updateTime();
6051 }
6052
6053 /*!
6054  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6055  *
6056  * \sa orientCorrectly2DCells
6057  */
6058 void MEDCouplingUMesh::changeOrientationOfCells()
6059 {
6060   int mdim(getMeshDimension());
6061   if(mdim!=2 && mdim!=1)
6062     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6063   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6064   const int *connI(_nodal_connec_index->getConstPointer());
6065   if(mdim==2)
6066     {//2D
6067       for(int i=0;i<nbOfCells;i++)
6068         {
6069           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6070           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6071           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6072         }
6073     }
6074   else
6075     {//1D
6076       for(int i=0;i<nbOfCells;i++)
6077         {
6078           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6079           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6080           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6081         }
6082     }
6083 }
6084
6085 /*!
6086  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6087  * oriented facets. The normal vector of the facet should point out of the cell.
6088  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6089  *         is not cleared before filling in.
6090  *  \throw If \a this->getMeshDimension() != 3.
6091  *  \throw If \a this->getSpaceDimension() != 3.
6092  *  \throw If the coordinates array is not set.
6093  *  \throw If the nodal connectivity of cells is not defined.
6094  *
6095  *  \if ENABLE_EXAMPLES
6096  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6097  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6098  *  \endif
6099  */
6100 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6101 {
6102   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6103     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6104   int nbOfCells=getNumberOfCells();
6105   const int *conn=_nodal_connec->getConstPointer();
6106   const int *connI=_nodal_connec_index->getConstPointer();
6107   const double *coordsPtr=_coords->getConstPointer();
6108   for(int i=0;i<nbOfCells;i++)
6109     {
6110       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6111       if(type==INTERP_KERNEL::NORM_POLYHED)
6112         {
6113           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6114             cells.push_back(i);
6115         }
6116     }
6117 }
6118
6119 /*!
6120  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6121  * out of the cell. 
6122  *  \throw If \a this->getMeshDimension() != 3.
6123  *  \throw If \a this->getSpaceDimension() != 3.
6124  *  \throw If the coordinates array is not set.
6125  *  \throw If the nodal connectivity of cells is not defined.
6126  *  \throw If the reparation fails.
6127  *
6128  *  \if ENABLE_EXAMPLES
6129  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6130  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6131  *  \endif
6132  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6133  */
6134 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6135 {
6136   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6137     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6138   int nbOfCells=getNumberOfCells();
6139   int *conn=_nodal_connec->getPointer();
6140   const int *connI=_nodal_connec_index->getConstPointer();
6141   const double *coordsPtr=_coords->getConstPointer();
6142   for(int i=0;i<nbOfCells;i++)
6143     {
6144       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6145       if(type==INTERP_KERNEL::NORM_POLYHED)
6146         {
6147           try
6148           {
6149               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6150                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6151           }
6152           catch(INTERP_KERNEL::Exception& e)
6153           {
6154               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6155               throw INTERP_KERNEL::Exception(oss.str().c_str());
6156           }
6157         }
6158     }
6159   updateTime();
6160 }
6161
6162 /*!
6163  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6164  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6165  * according to which the first facet of the cell should be oriented to have the normal vector
6166  * pointing out of cell.
6167  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6168  *         cells. The caller is to delete this array using decrRef() as it is no more
6169  *         needed. 
6170  *  \throw If \a this->getMeshDimension() != 3.
6171  *  \throw If \a this->getSpaceDimension() != 3.
6172  *  \throw If the coordinates array is not set.
6173  *  \throw If the nodal connectivity of cells is not defined.
6174  *
6175  *  \if ENABLE_EXAMPLES
6176  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6177  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6178  *  \endif
6179  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6180  */
6181 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6182 {
6183   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6184   if(getMeshDimension()!=3)
6185     throw INTERP_KERNEL::Exception(msg);
6186   int spaceDim=getSpaceDimension();
6187   if(spaceDim!=3)
6188     throw INTERP_KERNEL::Exception(msg);
6189   //
6190   int nbOfCells=getNumberOfCells();
6191   int *conn=_nodal_connec->getPointer();
6192   const int *connI=_nodal_connec_index->getConstPointer();
6193   const double *coo=getCoords()->getConstPointer();
6194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6195   for(int i=0;i<nbOfCells;i++)
6196     {
6197       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6198       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6199         {
6200           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6201             {
6202               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6203               cells->pushBackSilent(i);
6204             }
6205         }
6206     }
6207   return cells.retn();
6208 }
6209
6210 /*!
6211  * This method is a faster method to correct orientation of all 3D cells in \a this.
6212  * 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.
6213  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6214  * 
6215  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6216  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6217  */
6218 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6219 {
6220   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6221     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6222   int nbOfCells=getNumberOfCells();
6223   int *conn=_nodal_connec->getPointer();
6224   const int *connI=_nodal_connec_index->getConstPointer();
6225   const double *coordsPtr=_coords->getConstPointer();
6226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6227   for(int i=0;i<nbOfCells;i++)
6228     {
6229       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6230       switch(type)
6231       {
6232         case INTERP_KERNEL::NORM_TETRA4:
6233           {
6234             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6235               {
6236                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6237                 ret->pushBackSilent(i);
6238               }
6239             break;
6240           }
6241         case INTERP_KERNEL::NORM_PYRA5:
6242           {
6243             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6244               {
6245                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6246                 ret->pushBackSilent(i);
6247               }
6248             break;
6249           }
6250         case INTERP_KERNEL::NORM_PENTA6:
6251         case INTERP_KERNEL::NORM_HEXA8:
6252         case INTERP_KERNEL::NORM_HEXGP12:
6253           {
6254             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6255               {
6256                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6257                 ret->pushBackSilent(i);
6258               }
6259             break;
6260           }
6261         case INTERP_KERNEL::NORM_POLYHED:
6262           {
6263             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6264               {
6265                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6266                 ret->pushBackSilent(i);
6267               }
6268             break;
6269           }
6270         default:
6271           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 !");
6272       }
6273     }
6274   updateTime();
6275   return ret.retn();
6276 }
6277
6278 /*!
6279  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6280  * If it is not the case an exception will be thrown.
6281  * This method is fast because the first cell of \a this is used to compute the plane.
6282  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6283  * \param pos output of size at least 3 used to store a point owned of searched plane.
6284  */
6285 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6286 {
6287   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6288     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6289   const int *conn=_nodal_connec->getConstPointer();
6290   const int *connI=_nodal_connec_index->getConstPointer();
6291   const double *coordsPtr=_coords->getConstPointer();
6292   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6293   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6294 }
6295
6296 /*!
6297  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6298  * cells. Currently cells of the following types are treated:
6299  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6300  * For a cell of other type an exception is thrown.
6301  * Space dimension of a 2D mesh can be either 2 or 3.
6302  * The Edge Ratio of a cell \f$t\f$ is: 
6303  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6304  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6305  *  the smallest edge lengths of \f$t\f$.
6306  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6307  *          cells and one time, lying on \a this mesh. The caller is to delete this
6308  *          field using decrRef() as it is no more needed. 
6309  *  \throw If the coordinates array is not set.
6310  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6311  *  \throw If the connectivity data array has more than one component.
6312  *  \throw If the connectivity data array has a named component.
6313  *  \throw If the connectivity index data array has more than one component.
6314  *  \throw If the connectivity index data array has a named component.
6315  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6316  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6317  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6318  */
6319 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6320 {
6321   checkCoherency();
6322   int spaceDim=getSpaceDimension();
6323   int meshDim=getMeshDimension();
6324   if(spaceDim!=2 && spaceDim!=3)
6325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6326   if(meshDim!=2 && meshDim!=3)
6327     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6328   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6329   ret->setMesh(this);
6330   int nbOfCells=getNumberOfCells();
6331   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6332   arr->alloc(nbOfCells,1);
6333   double *pt=arr->getPointer();
6334   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6335   const int *conn=_nodal_connec->getConstPointer();
6336   const int *connI=_nodal_connec_index->getConstPointer();
6337   const double *coo=_coords->getConstPointer();
6338   double tmp[12];
6339   for(int i=0;i<nbOfCells;i++,pt++)
6340     {
6341       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6342       switch(t)
6343       {
6344         case INTERP_KERNEL::NORM_TRI3:
6345           {
6346             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6347             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6348             break;
6349           }
6350         case INTERP_KERNEL::NORM_QUAD4:
6351           {
6352             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6353             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6354             break;
6355           }
6356         case INTERP_KERNEL::NORM_TETRA4:
6357           {
6358             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6359             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6360             break;
6361           }
6362         default:
6363           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6364       }
6365       conn+=connI[i+1]-connI[i];
6366     }
6367   ret->setName("EdgeRatio");
6368   ret->synchronizeTimeWithSupport();
6369   return ret.retn();
6370 }
6371
6372 /*!
6373  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6374  * cells. Currently cells of the following types are treated:
6375  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6376  * For a cell of other type an exception is thrown.
6377  * Space dimension of a 2D mesh can be either 2 or 3.
6378  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6379  *          cells and one time, lying on \a this mesh. The caller is to delete this
6380  *          field using decrRef() as it is no more needed. 
6381  *  \throw If the coordinates array is not set.
6382  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6383  *  \throw If the connectivity data array has more than one component.
6384  *  \throw If the connectivity data array has a named component.
6385  *  \throw If the connectivity index data array has more than one component.
6386  *  \throw If the connectivity index data array has a named component.
6387  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6388  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6389  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6390  */
6391 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6392 {
6393   checkCoherency();
6394   int spaceDim=getSpaceDimension();
6395   int meshDim=getMeshDimension();
6396   if(spaceDim!=2 && spaceDim!=3)
6397     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6398   if(meshDim!=2 && meshDim!=3)
6399     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6400   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6401   ret->setMesh(this);
6402   int nbOfCells=getNumberOfCells();
6403   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6404   arr->alloc(nbOfCells,1);
6405   double *pt=arr->getPointer();
6406   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6407   const int *conn=_nodal_connec->getConstPointer();
6408   const int *connI=_nodal_connec_index->getConstPointer();
6409   const double *coo=_coords->getConstPointer();
6410   double tmp[12];
6411   for(int i=0;i<nbOfCells;i++,pt++)
6412     {
6413       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6414       switch(t)
6415       {
6416         case INTERP_KERNEL::NORM_TRI3:
6417           {
6418             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6419             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6420             break;
6421           }
6422         case INTERP_KERNEL::NORM_QUAD4:
6423           {
6424             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6425             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6426             break;
6427           }
6428         case INTERP_KERNEL::NORM_TETRA4:
6429           {
6430             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6431             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6432             break;
6433           }
6434         default:
6435           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6436       }
6437       conn+=connI[i+1]-connI[i];
6438     }
6439   ret->setName("AspectRatio");
6440   ret->synchronizeTimeWithSupport();
6441   return ret.retn();
6442 }
6443
6444 /*!
6445  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6446  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6447  * treated: INTERP_KERNEL::NORM_QUAD4.
6448  * For a cell of other type an exception is thrown.
6449  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6450  *          cells and one time, lying on \a this mesh. The caller is to delete this
6451  *          field using decrRef() as it is no more needed. 
6452  *  \throw If the coordinates array is not set.
6453  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6454  *  \throw If the connectivity data array has more than one component.
6455  *  \throw If the connectivity data array has a named component.
6456  *  \throw If the connectivity index data array has more than one component.
6457  *  \throw If the connectivity index data array has a named component.
6458  *  \throw If \a this->getMeshDimension() != 2.
6459  *  \throw If \a this->getSpaceDimension() != 3.
6460  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6461  */
6462 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6463 {
6464   checkCoherency();
6465   int spaceDim=getSpaceDimension();
6466   int meshDim=getMeshDimension();
6467   if(spaceDim!=3)
6468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6469   if(meshDim!=2)
6470     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6471   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6472   ret->setMesh(this);
6473   int nbOfCells=getNumberOfCells();
6474   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6475   arr->alloc(nbOfCells,1);
6476   double *pt=arr->getPointer();
6477   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6478   const int *conn=_nodal_connec->getConstPointer();
6479   const int *connI=_nodal_connec_index->getConstPointer();
6480   const double *coo=_coords->getConstPointer();
6481   double tmp[12];
6482   for(int i=0;i<nbOfCells;i++,pt++)
6483     {
6484       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6485       switch(t)
6486       {
6487         case INTERP_KERNEL::NORM_QUAD4:
6488           {
6489             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6490             *pt=INTERP_KERNEL::quadWarp(tmp);
6491             break;
6492           }
6493         default:
6494           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6495       }
6496       conn+=connI[i+1]-connI[i];
6497     }
6498   ret->setName("Warp");
6499   ret->synchronizeTimeWithSupport();
6500   return ret.retn();
6501 }
6502
6503
6504 /*!
6505  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6506  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6507  * treated: INTERP_KERNEL::NORM_QUAD4.
6508  * For a cell of other type an exception is thrown.
6509  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6510  *          cells and one time, lying on \a this mesh. The caller is to delete this
6511  *          field using decrRef() as it is no more needed. 
6512  *  \throw If the coordinates array is not set.
6513  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6514  *  \throw If the connectivity data array has more than one component.
6515  *  \throw If the connectivity data array has a named component.
6516  *  \throw If the connectivity index data array has more than one component.
6517  *  \throw If the connectivity index data array has a named component.
6518  *  \throw If \a this->getMeshDimension() != 2.
6519  *  \throw If \a this->getSpaceDimension() != 3.
6520  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6521  */
6522 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6523 {
6524   checkCoherency();
6525   int spaceDim=getSpaceDimension();
6526   int meshDim=getMeshDimension();
6527   if(spaceDim!=3)
6528     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6529   if(meshDim!=2)
6530     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6531   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6532   ret->setMesh(this);
6533   int nbOfCells=getNumberOfCells();
6534   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6535   arr->alloc(nbOfCells,1);
6536   double *pt=arr->getPointer();
6537   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6538   const int *conn=_nodal_connec->getConstPointer();
6539   const int *connI=_nodal_connec_index->getConstPointer();
6540   const double *coo=_coords->getConstPointer();
6541   double tmp[12];
6542   for(int i=0;i<nbOfCells;i++,pt++)
6543     {
6544       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6545       switch(t)
6546       {
6547         case INTERP_KERNEL::NORM_QUAD4:
6548           {
6549             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6550             *pt=INTERP_KERNEL::quadSkew(tmp);
6551             break;
6552           }
6553         default:
6554           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6555       }
6556       conn+=connI[i+1]-connI[i];
6557     }
6558   ret->setName("Skew");
6559   ret->synchronizeTimeWithSupport();
6560   return ret.retn();
6561 }
6562
6563 /*!
6564  * 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.
6565  *
6566  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6567  *
6568  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6569  */
6570 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6571 {
6572   checkCoherency();
6573   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6574   ret->setMesh(this);
6575   std::set<INTERP_KERNEL::NormalizedCellType> types;
6576   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6577   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6578   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6579   arr->alloc(nbCells,1);
6580   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6581     {
6582       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6583       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6584       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6585     }
6586   ret->setArray(arr);
6587   ret->setName("Diameter");
6588   return ret.retn();
6589 }
6590
6591 /*!
6592  * This method aggregate the bbox of each cell and put it into bbox parameter.
6593  * 
6594  * \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)
6595  *                         For all other cases this input parameter is ignored.
6596  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6597  * 
6598  * \throw If \a this is not fully set (coordinates and connectivity).
6599  * \throw If a cell in \a this has no valid nodeId.
6600  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6601  */
6602 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6603 {
6604   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6605   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.
6606     return getBoundingBoxForBBTreeFast();
6607   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6608     {
6609       bool presenceOfQuadratic(false);
6610       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6611         {
6612           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6613           if(cm.isQuadratic())
6614             presenceOfQuadratic=true;
6615         }
6616       if(!presenceOfQuadratic)
6617         return getBoundingBoxForBBTreeFast();
6618       if(mDim==2 && sDim==2)
6619         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6620       else
6621         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6622     }
6623   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) !");
6624 }
6625
6626 /*!
6627  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6628  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6629  * 
6630  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6631  * 
6632  * \throw If \a this is not fully set (coordinates and connectivity).
6633  * \throw If a cell in \a this has no valid nodeId.
6634  */
6635 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6636 {
6637   checkFullyDefined();
6638   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6639   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6640   double *bbox(ret->getPointer());
6641   for(int i=0;i<nbOfCells*spaceDim;i++)
6642     {
6643       bbox[2*i]=std::numeric_limits<double>::max();
6644       bbox[2*i+1]=-std::numeric_limits<double>::max();
6645     }
6646   const double *coordsPtr(_coords->getConstPointer());
6647   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6648   for(int i=0;i<nbOfCells;i++)
6649     {
6650       int offset=connI[i]+1;
6651       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6652       for(int j=0;j<nbOfNodesForCell;j++)
6653         {
6654           int nodeId=conn[offset+j];
6655           if(nodeId>=0 && nodeId<nbOfNodes)
6656             {
6657               for(int k=0;k<spaceDim;k++)
6658                 {
6659                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6660                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6661                 }
6662               kk++;
6663             }
6664         }
6665       if(kk==0)
6666         {
6667           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6668           throw INTERP_KERNEL::Exception(oss.str().c_str());
6669         }
6670     }
6671   return ret.retn();
6672 }
6673
6674 /*!
6675  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6676  * useful for 2D meshes having quadratic cells
6677  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6678  * the two extremities of the arc of circle).
6679  * 
6680  * \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)
6681  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6682  * \throw If \a this is not fully defined.
6683  * \throw If \a this is not a mesh with meshDimension equal to 2.
6684  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6685  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6686  */
6687 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6688 {
6689   checkFullyDefined();
6690   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6691   if(spaceDim!=2 || mDim!=2)
6692     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!");
6693   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6694   double *bbox(ret->getPointer());
6695   const double *coords(_coords->getConstPointer());
6696   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6697   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6698     {
6699       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6700       int sz(connI[1]-connI[0]-1);
6701       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6702       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6703       INTERP_KERNEL::QuadraticPolygon *pol(0);
6704       for(int j=0;j<sz;j++)
6705         {
6706           int nodeId(conn[*connI+1+j]);
6707           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6708         }
6709       if(!cm.isQuadratic())
6710         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6711       else
6712         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6713       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6714       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6715     }
6716   return ret.retn();
6717 }
6718
6719 /*!
6720  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6721  * useful for 2D meshes having quadratic cells
6722  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6723  * the two extremities of the arc of circle).
6724  * 
6725  * \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)
6726  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6727  * \throw If \a this is not fully defined.
6728  * \throw If \a this is not a mesh with meshDimension equal to 1.
6729  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6730  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6731  */
6732 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6733 {
6734   checkFullyDefined();
6735   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6736   if(spaceDim!=2 || mDim!=1)
6737     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!");
6738   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6739   double *bbox(ret->getPointer());
6740   const double *coords(_coords->getConstPointer());
6741   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6742   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6743     {
6744       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6745       int sz(connI[1]-connI[0]-1);
6746       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6747       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6748       INTERP_KERNEL::Edge *edge(0);
6749       for(int j=0;j<sz;j++)
6750         {
6751           int nodeId(conn[*connI+1+j]);
6752           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6753         }
6754       if(!cm.isQuadratic())
6755         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6756       else
6757         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6758       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6759       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6760     }
6761   return ret.retn();
6762 }
6763
6764 /// @cond INTERNAL
6765
6766 namespace ParaMEDMEMImpl
6767 {
6768   class ConnReader
6769   {
6770   public:
6771     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6772     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6773   private:
6774     const int *_conn;
6775     int _val;
6776   };
6777
6778   class ConnReader2
6779   {
6780   public:
6781     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6782     bool operator() (const int& pos) { return _conn[pos]==_val; }
6783   private:
6784     const int *_conn;
6785     int _val;
6786   };
6787 }
6788
6789 /// @endcond
6790
6791 /*!
6792  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6793  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6794  * \a this is composed in cell types.
6795  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6796  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6797  * This parameter is kept only for compatibility with other methode listed above.
6798  */
6799 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6800 {
6801   checkConnectivityFullyDefined();
6802   const int *conn=_nodal_connec->getConstPointer();
6803   const int *connI=_nodal_connec_index->getConstPointer();
6804   const int *work=connI;
6805   int nbOfCells=getNumberOfCells();
6806   std::size_t n=getAllGeoTypes().size();
6807   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6808   std::set<INTERP_KERNEL::NormalizedCellType> types;
6809   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6810     {
6811       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6812       if(types.find(typ)!=types.end())
6813         {
6814           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6815           oss << " is not contiguous !";
6816           throw INTERP_KERNEL::Exception(oss.str().c_str());
6817         }
6818       types.insert(typ);
6819       ret[3*i]=typ;
6820       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6821       ret[3*i+1]=(int)std::distance(work,work2);
6822       work=work2;
6823     }
6824   return ret;
6825 }
6826
6827 /*!
6828  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6829  * only for types cell, type node is not managed.
6830  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6831  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6832  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6833  * If 2 or more same geometric type is in \a code and exception is thrown too.
6834  *
6835  * This method firstly checks
6836  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6837  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6838  * an exception is thrown too.
6839  * 
6840  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6841  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6842  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6843  */
6844 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6845 {
6846   if(code.empty())
6847     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6848   std::size_t sz=code.size();
6849   std::size_t n=sz/3;
6850   if(sz%3!=0)
6851     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6852   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6853   int nb=0;
6854   bool isNoPflUsed=true;
6855   for(std::size_t i=0;i<n;i++)
6856     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6857       {
6858         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6859         nb+=code[3*i+1];
6860         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6861           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6862         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6863       }
6864   if(types.size()!=n)
6865     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6866   if(isNoPflUsed)
6867     {
6868       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6869         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6870       if(types.size()==_types.size())
6871         return 0;
6872     }
6873   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6874   ret->alloc(nb,1);
6875   int *retPtr=ret->getPointer();
6876   const int *connI=_nodal_connec_index->getConstPointer();
6877   const int *conn=_nodal_connec->getConstPointer();
6878   int nbOfCells=getNumberOfCells();
6879   const int *i=connI;
6880   int kk=0;
6881   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6882     {
6883       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6884       int offset=(int)std::distance(connI,i);
6885       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6886       int nbOfCellsOfCurType=(int)std::distance(i,j);
6887       if(code[3*kk+2]==-1)
6888         for(int k=0;k<nbOfCellsOfCurType;k++)
6889           *retPtr++=k+offset;
6890       else
6891         {
6892           int idInIdsPerType=code[3*kk+2];
6893           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6894             {
6895               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6896               if(zePfl)
6897                 {
6898                   zePfl->checkAllocated();
6899                   if(zePfl->getNumberOfComponents()==1)
6900                     {
6901                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6902                         {
6903                           if(*k>=0 && *k<nbOfCellsOfCurType)
6904                             *retPtr=(*k)+offset;
6905                           else
6906                             {
6907                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6908                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6909                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6910                             }
6911                         }
6912                     }
6913                   else
6914                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6915                 }
6916               else
6917                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6918             }
6919           else
6920             {
6921               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6922               oss << " should be in [0," << idsPerType.size() << ") !";
6923               throw INTERP_KERNEL::Exception(oss.str().c_str());
6924             }
6925         }
6926       i=j;
6927     }
6928   return ret.retn();
6929 }
6930
6931 /*!
6932  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6933  * 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.
6934  * 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.
6935  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6936  * 
6937  * \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.
6938  * \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,
6939  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6940  * \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.
6941  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6942  * \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
6943  */
6944 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6945 {
6946   if(!profile)
6947     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6948   if(profile->getNumberOfComponents()!=1)
6949     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6950   checkConnectivityFullyDefined();
6951   const int *conn=_nodal_connec->getConstPointer();
6952   const int *connI=_nodal_connec_index->getConstPointer();
6953   int nbOfCells=getNumberOfCells();
6954   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6955   std::vector<int> typeRangeVals(1);
6956   for(const int *i=connI;i!=connI+nbOfCells;)
6957     {
6958       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6959       if(std::find(types.begin(),types.end(),curType)!=types.end())
6960         {
6961           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6962         }
6963       types.push_back(curType);
6964       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6965       typeRangeVals.push_back((int)std::distance(connI,i));
6966     }
6967   //
6968   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6969   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6971   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6972   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6973   //
6974   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6975   code.resize(3*nbOfCastsFinal);
6976   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6977   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6978   for(int i=0;i<nbOfCastsFinal;i++)
6979     {
6980       int castId=castsPresent->getIJ(i,0);
6981       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6982       idsInPflPerType2.push_back(tmp3);
6983       code[3*i]=(int)types[castId];
6984       code[3*i+1]=tmp3->getNumberOfTuples();
6985       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6986       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6987         {
6988           tmp4->copyStringInfoFrom(*profile);
6989           idsPerType2.push_back(tmp4);
6990           code[3*i+2]=(int)idsPerType2.size()-1;
6991         }
6992       else
6993         {
6994           code[3*i+2]=-1;
6995         }
6996     }
6997   std::size_t sz2=idsInPflPerType2.size();
6998   idsInPflPerType.resize(sz2);
6999   for(std::size_t i=0;i<sz2;i++)
7000     {
7001       DataArrayInt *locDa=idsInPflPerType2[i];
7002       locDa->incrRef();
7003       idsInPflPerType[i]=locDa;
7004     }
7005   std::size_t sz=idsPerType2.size();
7006   idsPerType.resize(sz);
7007   for(std::size_t i=0;i<sz;i++)
7008     {
7009       DataArrayInt *locDa=idsPerType2[i];
7010       locDa->incrRef();
7011       idsPerType[i]=locDa;
7012     }
7013 }
7014
7015 /*!
7016  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7017  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7018  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7019  * 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.
7020  */
7021 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7022 {
7023   checkFullyDefined();
7024   nM1LevMesh->checkFullyDefined();
7025   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7026     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7027   if(_coords!=nM1LevMesh->getCoords())
7028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7029   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7030   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7031   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7032   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7033   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7034   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7035   tmp->setConnectivity(tmp0,tmp1);
7036   tmp->renumberCells(ret0->getConstPointer(),false);
7037   revDesc=tmp->getNodalConnectivity();
7038   revDescIndx=tmp->getNodalConnectivityIndex();
7039   DataArrayInt *ret=0;
7040   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7041     {
7042       int tmp2;
7043       ret->getMaxValue(tmp2);
7044       ret->decrRef();
7045       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7046       throw INTERP_KERNEL::Exception(oss.str().c_str());
7047     }
7048   nM1LevMeshIds=ret;
7049   //
7050   revDesc->incrRef();
7051   revDescIndx->incrRef();
7052   ret1->incrRef();
7053   ret0->incrRef();
7054   meshnM1Old2New=ret0;
7055   return ret1;
7056 }
7057
7058 /*!
7059  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7060  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7061  * in "Old to New" mode.
7062  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7063  *          this array using decrRef() as it is no more needed.
7064  *  \throw If the nodal connectivity of cells is not defined.
7065  */
7066 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7067 {
7068   checkConnectivityFullyDefined();
7069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7070   renumberCells(ret->getConstPointer(),false);
7071   return ret.retn();
7072 }
7073
7074 /*!
7075  * This methods checks that cells are sorted by their types.
7076  * This method makes asumption (no check) that connectivity is correctly set before calling.
7077  */
7078 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7079 {
7080   checkFullyDefined();
7081   const int *conn=_nodal_connec->getConstPointer();
7082   const int *connI=_nodal_connec_index->getConstPointer();
7083   int nbOfCells=getNumberOfCells();
7084   std::set<INTERP_KERNEL::NormalizedCellType> types;
7085   for(const int *i=connI;i!=connI+nbOfCells;)
7086     {
7087       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7088       if(types.find(curType)!=types.end())
7089         return false;
7090       types.insert(curType);
7091       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7092     }
7093   return true;
7094 }
7095
7096 /*!
7097  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7098  * The geometric type order is specified by MED file.
7099  * 
7100  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7101  */
7102 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7103 {
7104   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7105 }
7106
7107 /*!
7108  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7109  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7110  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7111  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7112  */
7113 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7114 {
7115   checkFullyDefined();
7116   const int *conn=_nodal_connec->getConstPointer();
7117   const int *connI=_nodal_connec_index->getConstPointer();
7118   int nbOfCells=getNumberOfCells();
7119   if(nbOfCells==0)
7120     return true;
7121   int lastPos=-1;
7122   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7123   for(const int *i=connI;i!=connI+nbOfCells;)
7124     {
7125       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7126       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7127       if(isTypeExists!=orderEnd)
7128         {
7129           int pos=(int)std::distance(orderBg,isTypeExists);
7130           if(pos<=lastPos)
7131             return false;
7132           lastPos=pos;
7133           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7134         }
7135       else
7136         {
7137           if(sg.find(curType)==sg.end())
7138             {
7139               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7140               sg.insert(curType);
7141             }
7142           else
7143             return false;
7144         }
7145     }
7146   return true;
7147 }
7148
7149 /*!
7150  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7151  * 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
7152  * 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'.
7153  */
7154 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7155 {
7156   checkConnectivityFullyDefined();
7157   int nbOfCells=getNumberOfCells();
7158   const int *conn=_nodal_connec->getConstPointer();
7159   const int *connI=_nodal_connec_index->getConstPointer();
7160   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7161   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7162   tmpa->alloc(nbOfCells,1);
7163   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7164   tmpb->fillWithZero();
7165   int *tmp=tmpa->getPointer();
7166   int *tmp2=tmpb->getPointer();
7167   for(const int *i=connI;i!=connI+nbOfCells;i++)
7168     {
7169       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7170       if(where!=orderEnd)
7171         {
7172           int pos=(int)std::distance(orderBg,where);
7173           tmp2[pos]++;
7174           tmp[std::distance(connI,i)]=pos;
7175         }
7176       else
7177         {
7178           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7179           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7180           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7181           throw INTERP_KERNEL::Exception(oss.str().c_str());
7182         }
7183     }
7184   nbPerType=tmpb.retn();
7185   return tmpa.retn();
7186 }
7187
7188 /*!
7189  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7190  *
7191  * \return a new object containing the old to new correspondance.
7192  *
7193  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7194  */
7195 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7196 {
7197   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7198 }
7199
7200 /*!
7201  * 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.
7202  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7203  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7204  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7205  */
7206 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7207 {
7208   DataArrayInt *nbPerType=0;
7209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7210   nbPerType->decrRef();
7211   return tmpa->buildPermArrPerLevel();
7212 }
7213
7214 /*!
7215  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7216  * The number of cells remains unchanged after the call of this method.
7217  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7218  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7219  *
7220  * \return the array giving the correspondance old to new.
7221  */
7222 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7223 {
7224   checkFullyDefined();
7225   computeTypes();
7226   const int *conn=_nodal_connec->getConstPointer();
7227   const int *connI=_nodal_connec_index->getConstPointer();
7228   int nbOfCells=getNumberOfCells();
7229   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7230   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7231     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7232       {
7233         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7234         types.push_back(curType);
7235         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7236       }
7237   DataArrayInt *ret=DataArrayInt::New();
7238   ret->alloc(nbOfCells,1);
7239   int *retPtr=ret->getPointer();
7240   std::fill(retPtr,retPtr+nbOfCells,-1);
7241   int newCellId=0;
7242   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7243     {
7244       for(const int *i=connI;i!=connI+nbOfCells;i++)
7245         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7246           retPtr[std::distance(connI,i)]=newCellId++;
7247     }
7248   renumberCells(retPtr,false);
7249   return ret;
7250 }
7251
7252 /*!
7253  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7254  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7255  * This method makes asumption that connectivity is correctly set before calling.
7256  */
7257 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7258 {
7259   checkConnectivityFullyDefined();
7260   const int *conn=_nodal_connec->getConstPointer();
7261   const int *connI=_nodal_connec_index->getConstPointer();
7262   int nbOfCells=getNumberOfCells();
7263   std::vector<MEDCouplingUMesh *> ret;
7264   for(const int *i=connI;i!=connI+nbOfCells;)
7265     {
7266       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7267       int beginCellId=(int)std::distance(connI,i);
7268       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7269       int endCellId=(int)std::distance(connI,i);
7270       int sz=endCellId-beginCellId;
7271       int *cells=new int[sz];
7272       for(int j=0;j<sz;j++)
7273         cells[j]=beginCellId+j;
7274       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7275       delete [] cells;
7276       ret.push_back(m);
7277     }
7278   return ret;
7279 }
7280
7281 /*!
7282  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7283  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7284  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7285  *
7286  * \return a newly allocated instance, that the caller must manage.
7287  * \throw If \a this contains more than one geometric type.
7288  * \throw If the nodal connectivity of \a this is not fully defined.
7289  * \throw If the internal data is not coherent.
7290  */
7291 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7292 {
7293   checkConnectivityFullyDefined();
7294   if(_types.size()!=1)
7295     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7296   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7297   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7298   ret->setCoords(getCoords());
7299   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7300   if(retC)
7301     {
7302       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7303       retC->setNodalConnectivity(c);
7304     }
7305   else
7306     {
7307       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7308       if(!retD)
7309         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7310       DataArrayInt *c=0,*ci=0;
7311       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7312       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7313       retD->setNodalConnectivity(cs,cis);
7314     }
7315   return ret.retn();
7316 }
7317
7318 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7319 {
7320   checkConnectivityFullyDefined();
7321   if(_types.size()!=1)
7322     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7323   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7324   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7325   if(cm.isDynamic())
7326     {
7327       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7328       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7329       throw INTERP_KERNEL::Exception(oss.str().c_str());
7330     }
7331   int nbCells=getNumberOfCells();
7332   int typi=(int)typ;
7333   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7335   int *outPtr=connOut->getPointer();
7336   const int *conn=_nodal_connec->begin();
7337   const int *connI=_nodal_connec_index->begin();
7338   nbNodesPerCell++;
7339   for(int i=0;i<nbCells;i++,connI++)
7340     {
7341       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7342         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7343       else
7344         {
7345           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 << ") !";
7346           throw INTERP_KERNEL::Exception(oss.str().c_str());
7347         }
7348     }
7349   return connOut.retn();
7350 }
7351
7352 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7353 {
7354   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7355   checkConnectivityFullyDefined();
7356   if(_types.size()!=1)
7357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7358   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7359   if(lgth<nbCells)
7360     throw INTERP_KERNEL::Exception(msg0);
7361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7362   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7363   int *cp(c->getPointer()),*cip(ci->getPointer());
7364   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7365   cip[0]=0;
7366   for(int i=0;i<nbCells;i++,cip++,incip++)
7367     {
7368       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7369       int delta(stop-strt);
7370       if(delta>=1)
7371         {
7372           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7373             cp=std::copy(incp+strt,incp+stop,cp);
7374           else
7375             throw INTERP_KERNEL::Exception(msg0);
7376         }
7377       else
7378         throw INTERP_KERNEL::Exception(msg0);
7379       cip[1]=cip[0]+delta;
7380     }
7381   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7382 }
7383
7384 /*!
7385  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7386  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7387  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7388  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7389  * are not used here to avoid the build of big permutation array.
7390  *
7391  * \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
7392  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7393  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7394  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7395  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7396  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7397  * \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
7398  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7399  */
7400 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7401                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7402                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7403 {
7404   std::vector<const MEDCouplingUMesh *> ms2;
7405   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7406     if(*it)
7407       {
7408         (*it)->checkConnectivityFullyDefined();
7409         ms2.push_back(*it);
7410       }
7411   if(ms2.empty())
7412     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7413   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7414   int meshDim=ms2[0]->getMeshDimension();
7415   std::vector<const MEDCouplingUMesh *> m1ssm;
7416   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7417   //
7418   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7419   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7420   int fake=0,rk=0;
7421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7422   ret1->alloc(0,1); ret2->alloc(0,1);
7423   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7424     {
7425       if(meshDim!=(*it)->getMeshDimension())
7426         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7427       if(refCoo!=(*it)->getCoords())
7428         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7429       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7430       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7431       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7432       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7433         {
7434           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7435           m1ssmSingleAuto.push_back(singleCell);
7436           m1ssmSingle.push_back(singleCell);
7437           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7438         }
7439     }
7440   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7441   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7442   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7443   for(std::size_t i=0;i<m1ssm.size();i++)
7444     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7445   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7446   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7447   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7448   return ret0.retn();
7449 }
7450
7451 /*!
7452  * This method returns a newly created DataArrayInt instance.
7453  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7454  */
7455 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7456 {
7457   checkFullyDefined();
7458   const int *conn=_nodal_connec->getConstPointer();
7459   const int *connIndex=_nodal_connec_index->getConstPointer();
7460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7461   for(const int *w=begin;w!=end;w++)
7462     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7463       ret->pushBackSilent(*w);
7464   return ret.retn();
7465 }
7466
7467 /*!
7468  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7469  * are in [0:getNumberOfCells())
7470  */
7471 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7472 {
7473   checkFullyDefined();
7474   const int *conn=_nodal_connec->getConstPointer();
7475   const int *connI=_nodal_connec_index->getConstPointer();
7476   int nbOfCells=getNumberOfCells();
7477   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7478   int *tmp=new int[nbOfCells];
7479   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7480     {
7481       int j=0;
7482       for(const int *i=connI;i!=connI+nbOfCells;i++)
7483         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7484           tmp[std::distance(connI,i)]=j++;
7485     }
7486   DataArrayInt *ret=DataArrayInt::New();
7487   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7488   ret->copyStringInfoFrom(*da);
7489   int *retPtr=ret->getPointer();
7490   const int *daPtr=da->getConstPointer();
7491   int nbOfElems=da->getNbOfElems();
7492   for(int k=0;k<nbOfElems;k++)
7493     retPtr[k]=tmp[daPtr[k]];
7494   delete [] tmp;
7495   return ret;
7496 }
7497
7498 /*!
7499  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7500  * This method \b works \b for mesh sorted by type.
7501  * cells whose ids is in 'idsPerGeoType' array.
7502  * This method conserves coords and name of mesh.
7503  */
7504 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7505 {
7506   std::vector<int> code=getDistributionOfTypes();
7507   std::size_t nOfTypesInThis=code.size()/3;
7508   int sz=0,szOfType=0;
7509   for(std::size_t i=0;i<nOfTypesInThis;i++)
7510     {
7511       if(code[3*i]!=type)
7512         sz+=code[3*i+1];
7513       else
7514         szOfType=code[3*i+1];
7515     }
7516   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7517     if(*work<0 || *work>=szOfType)
7518       {
7519         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7520         oss << ". It should be in [0," << szOfType << ") !";
7521         throw INTERP_KERNEL::Exception(oss.str().c_str());
7522       }
7523   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7524   int *idsPtr=idsTokeep->getPointer();
7525   int offset=0;
7526   for(std::size_t i=0;i<nOfTypesInThis;i++)
7527     {
7528       if(code[3*i]!=type)
7529         for(int j=0;j<code[3*i+1];j++)
7530           *idsPtr++=offset+j;
7531       else
7532         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7533       offset+=code[3*i+1];
7534     }
7535   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7536   ret->copyTinyInfoFrom(this);
7537   return ret.retn();
7538 }
7539
7540 /*!
7541  * This method returns a vector of size 'this->getNumberOfCells()'.
7542  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7543  */
7544 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7545 {
7546   int ncell=getNumberOfCells();
7547   std::vector<bool> ret(ncell);
7548   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7549   const int *c=getNodalConnectivity()->getConstPointer();
7550   for(int i=0;i<ncell;i++)
7551     {
7552       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7553       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7554       ret[i]=cm.isQuadratic();
7555     }
7556   return ret;
7557 }
7558
7559 /*!
7560  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7561  */
7562 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7563 {
7564   if(other->getType()!=UNSTRUCTURED)
7565     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7566   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7567   return MergeUMeshes(this,otherC);
7568 }
7569
7570 /*!
7571  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7572  * computed by averaging coordinates of cell nodes, so this method is not a right
7573  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7574  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7575  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7576  *          components. The caller is to delete this array using decrRef() as it is
7577  *          no more needed.
7578  *  \throw If the coordinates array is not set.
7579  *  \throw If the nodal connectivity of cells is not defined.
7580  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7581  */
7582 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7583 {
7584   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7585   int spaceDim=getSpaceDimension();
7586   int nbOfCells=getNumberOfCells();
7587   ret->alloc(nbOfCells,spaceDim);
7588   ret->copyStringInfoFrom(*getCoords());
7589   double *ptToFill=ret->getPointer();
7590   const int *nodal=_nodal_connec->getConstPointer();
7591   const int *nodalI=_nodal_connec_index->getConstPointer();
7592   const double *coor=_coords->getConstPointer();
7593   for(int i=0;i<nbOfCells;i++)
7594     {
7595       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7596       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7597       ptToFill+=spaceDim;
7598     }
7599   return ret.retn();
7600 }
7601
7602 /*!
7603  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7604  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7605  * 
7606  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7607  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7608  * 
7609  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7610  * \throw If \a this is not fully defined (coordinates and connectivity)
7611  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7612  */
7613 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7614 {
7615   checkFullyDefined();
7616   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7617   int spaceDim=getSpaceDimension();
7618   int nbOfCells=getNumberOfCells();
7619   int nbOfNodes=getNumberOfNodes();
7620   ret->alloc(nbOfCells,spaceDim);
7621   double *ptToFill=ret->getPointer();
7622   const int *nodal=_nodal_connec->getConstPointer();
7623   const int *nodalI=_nodal_connec_index->getConstPointer();
7624   const double *coor=_coords->getConstPointer();
7625   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7626     {
7627       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7628       std::fill(ptToFill,ptToFill+spaceDim,0.);
7629       if(type!=INTERP_KERNEL::NORM_POLYHED)
7630         {
7631           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7632             {
7633               if(*conn>=0 && *conn<nbOfNodes)
7634                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7635               else
7636                 {
7637                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7638                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7639                 }
7640             }
7641           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7642           if(nbOfNodesInCell>0)
7643             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7644           else
7645             {
7646               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7647               throw INTERP_KERNEL::Exception(oss.str().c_str());
7648             }
7649         }
7650       else
7651         {
7652           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7653           s.erase(-1);
7654           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7655             {
7656               if(*it>=0 && *it<nbOfNodes)
7657                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7658               else
7659                 {
7660                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7661                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7662                 }
7663             }
7664           if(!s.empty())
7665             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7666           else
7667             {
7668               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7669               throw INTERP_KERNEL::Exception(oss.str().c_str());
7670             }
7671         }
7672     }
7673   return ret.retn();
7674 }
7675
7676 /*!
7677  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7678  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7679  * are specified via an array of cell ids. 
7680  *  \warning Validity of the specified cell ids is not checked! 
7681  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7682  *  \param [in] begin - an array of cell ids of interest.
7683  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7684  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7685  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7686  *          caller is to delete this array using decrRef() as it is no more needed. 
7687  *  \throw If the coordinates array is not set.
7688  *  \throw If the nodal connectivity of cells is not defined.
7689  *
7690  *  \if ENABLE_EXAMPLES
7691  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7692  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7693  *  \endif
7694  */
7695 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7696 {
7697   DataArrayDouble *ret=DataArrayDouble::New();
7698   int spaceDim=getSpaceDimension();
7699   int nbOfTuple=(int)std::distance(begin,end);
7700   ret->alloc(nbOfTuple,spaceDim);
7701   double *ptToFill=ret->getPointer();
7702   double *tmp=new double[spaceDim];
7703   const int *nodal=_nodal_connec->getConstPointer();
7704   const int *nodalI=_nodal_connec_index->getConstPointer();
7705   const double *coor=_coords->getConstPointer();
7706   for(const int *w=begin;w!=end;w++)
7707     {
7708       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7709       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7710       ptToFill+=spaceDim;
7711     }
7712   delete [] tmp;
7713   return ret;
7714 }
7715
7716 /*!
7717  * 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".
7718  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7719  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7720  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7721  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7722  * 
7723  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7724  * \throw If spaceDim!=3 or meshDim!=2.
7725  * \throw If connectivity of \a this is invalid.
7726  * \throw If connectivity of a cell in \a this points to an invalid node.
7727  */
7728 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7729 {
7730   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7731   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7732   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7733     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7734   ret->alloc(nbOfCells,4);
7735   double *retPtr(ret->getPointer());
7736   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7737   const double *coor(_coords->begin());
7738   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7739     {
7740       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7741       if(nodalI[1]-nodalI[0]>=3)
7742         {
7743           for(int j=0;j<3;j++)
7744             {
7745               int nodeId(nodal[nodalI[0]+1+j]);
7746               if(nodeId>=0 && nodeId<nbOfNodes)
7747                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7748               else
7749                 {
7750                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7751                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7752                 }
7753             }
7754         }
7755       else
7756         {
7757           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7758           throw INTERP_KERNEL::Exception(oss.str().c_str());
7759         }
7760       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7761       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7762     }
7763   return ret.retn();
7764 }
7765
7766 /*!
7767  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7768  * 
7769  */
7770 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7771 {
7772   if(!da)
7773     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7774   da->checkAllocated();
7775   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7776   ret->setCoords(da);
7777   int nbOfTuples=da->getNumberOfTuples();
7778   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7779   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7780   c->alloc(2*nbOfTuples,1);
7781   cI->alloc(nbOfTuples+1,1);
7782   int *cp=c->getPointer();
7783   int *cip=cI->getPointer();
7784   *cip++=0;
7785   for(int i=0;i<nbOfTuples;i++)
7786     {
7787       *cp++=INTERP_KERNEL::NORM_POINT1;
7788       *cp++=i;
7789       *cip++=2*(i+1);
7790     }
7791   ret->setConnectivity(c,cI,true);
7792   return ret.retn();
7793 }
7794 /*!
7795  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7796  * Cells and nodes of
7797  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7798  *  \param [in] mesh1 - the first mesh.
7799  *  \param [in] mesh2 - the second mesh.
7800  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7801  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7802  *          is no more needed.
7803  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7804  *  \throw If the coordinates array is not set in none of the meshes.
7805  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7806  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7807  */
7808 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7809 {
7810   std::vector<const MEDCouplingUMesh *> tmp(2);
7811   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7812   return MergeUMeshes(tmp);
7813 }
7814
7815 /*!
7816  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7817  * Cells and nodes of
7818  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7819  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7820  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7821  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7822  *          is no more needed.
7823  *  \throw If \a a.size() == 0.
7824  *  \throw If \a a[ *i* ] == NULL.
7825  *  \throw If the coordinates array is not set in none of the meshes.
7826  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7827  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7828  */
7829 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7830 {
7831   std::size_t sz=a.size();
7832   if(sz==0)
7833     return MergeUMeshesLL(a);
7834   for(std::size_t ii=0;ii<sz;ii++)
7835     if(!a[ii])
7836       {
7837         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7838         throw INTERP_KERNEL::Exception(oss.str().c_str());
7839       }
7840   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7841   std::vector< const MEDCouplingUMesh * > aa(sz);
7842   int spaceDim=-3;
7843   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7844     {
7845       const MEDCouplingUMesh *cur=a[i];
7846       const DataArrayDouble *coo=cur->getCoords();
7847       if(coo)
7848         spaceDim=coo->getNumberOfComponents();
7849     }
7850   if(spaceDim==-3)
7851     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7852   for(std::size_t i=0;i<sz;i++)
7853     {
7854       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7855       aa[i]=bb[i];
7856     }
7857   return MergeUMeshesLL(aa);
7858 }
7859
7860 /// @cond INTERNAL
7861
7862 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7863 {
7864   if(a.empty())
7865     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7866   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7867   int meshDim=(*it)->getMeshDimension();
7868   int nbOfCells=(*it)->getNumberOfCells();
7869   int meshLgth=(*it++)->getMeshLength();
7870   for(;it!=a.end();it++)
7871     {
7872       if(meshDim!=(*it)->getMeshDimension())
7873         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7874       nbOfCells+=(*it)->getNumberOfCells();
7875       meshLgth+=(*it)->getMeshLength();
7876     }
7877   std::vector<const MEDCouplingPointSet *> aps(a.size());
7878   std::copy(a.begin(),a.end(),aps.begin());
7879   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7880   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7881   ret->setCoords(pts);
7882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7883   c->alloc(meshLgth,1);
7884   int *cPtr=c->getPointer();
7885   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7886   cI->alloc(nbOfCells+1,1);
7887   int *cIPtr=cI->getPointer();
7888   *cIPtr++=0;
7889   int offset=0;
7890   int offset2=0;
7891   for(it=a.begin();it!=a.end();it++)
7892     {
7893       int curNbOfCell=(*it)->getNumberOfCells();
7894       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7895       const int *curC=(*it)->_nodal_connec->getConstPointer();
7896       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7897       for(int j=0;j<curNbOfCell;j++)
7898         {
7899           const int *src=curC+curCI[j];
7900           *cPtr++=*src++;
7901           for(;src!=curC+curCI[j+1];src++,cPtr++)
7902             {
7903               if(*src!=-1)
7904                 *cPtr=*src+offset2;
7905               else
7906                 *cPtr=-1;
7907             }
7908         }
7909       offset+=curCI[curNbOfCell];
7910       offset2+=(*it)->getNumberOfNodes();
7911     }
7912   //
7913   ret->setConnectivity(c,cI,true);
7914   return ret.retn();
7915 }
7916
7917 /// @endcond
7918
7919 /*!
7920  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7921  * dimension and sharing the node coordinates array.
7922  * All cells of the first mesh precede all cells of the second mesh
7923  * within the result mesh. 
7924  *  \param [in] mesh1 - the first mesh.
7925  *  \param [in] mesh2 - the second mesh.
7926  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7927  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7928  *          is no more needed.
7929  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7930  *  \throw If the meshes do not share the node coordinates array.
7931  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7932  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7933  */
7934 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7935 {
7936   std::vector<const MEDCouplingUMesh *> tmp(2);
7937   tmp[0]=mesh1; tmp[1]=mesh2;
7938   return MergeUMeshesOnSameCoords(tmp);
7939 }
7940
7941 /*!
7942  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7943  * dimension and sharing the node coordinates array.
7944  * All cells of the *i*-th mesh precede all cells of the
7945  * (*i*+1)-th mesh within the result mesh.
7946  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7947  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7948  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7949  *          is no more needed.
7950  *  \throw If \a a.size() == 0.
7951  *  \throw If \a a[ *i* ] == NULL.
7952  *  \throw If the meshes do not share the node coordinates array.
7953  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7954  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7955  */
7956 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7957 {
7958   if(meshes.empty())
7959     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7960   for(std::size_t ii=0;ii<meshes.size();ii++)
7961     if(!meshes[ii])
7962       {
7963         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7964         throw INTERP_KERNEL::Exception(oss.str().c_str());
7965       }
7966   const DataArrayDouble *coords=meshes.front()->getCoords();
7967   int meshDim=meshes.front()->getMeshDimension();
7968   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7969   int meshLgth=0;
7970   int meshIndexLgth=0;
7971   for(;iter!=meshes.end();iter++)
7972     {
7973       if(coords!=(*iter)->getCoords())
7974         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7975       if(meshDim!=(*iter)->getMeshDimension())
7976         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7977       meshLgth+=(*iter)->getMeshLength();
7978       meshIndexLgth+=(*iter)->getNumberOfCells();
7979     }
7980   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7981   nodal->alloc(meshLgth,1);
7982   int *nodalPtr=nodal->getPointer();
7983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7984   nodalIndex->alloc(meshIndexLgth+1,1);
7985   int *nodalIndexPtr=nodalIndex->getPointer();
7986   int offset=0;
7987   for(iter=meshes.begin();iter!=meshes.end();iter++)
7988     {
7989       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7990       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7991       int nbOfCells=(*iter)->getNumberOfCells();
7992       int meshLgth2=(*iter)->getMeshLength();
7993       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7994       if(iter!=meshes.begin())
7995         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7996       else
7997         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7998       offset+=meshLgth2;
7999     }
8000   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8001   ret->setName("merge");
8002   ret->setMeshDimension(meshDim);
8003   ret->setConnectivity(nodal,nodalIndex,true);
8004   ret->setCoords(coords);
8005   return ret;
8006 }
8007
8008 /*!
8009  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8010  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8011  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8012  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8013  * New" mode are returned for each input mesh.
8014  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8015  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8016  *          valid values [0,1,2], see zipConnectivityTraducer().
8017  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8018  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8019  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8020  *          no more needed.
8021  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8022  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8023  *          is no more needed.
8024  *  \throw If \a meshes.size() == 0.
8025  *  \throw If \a meshes[ *i* ] == NULL.
8026  *  \throw If the meshes do not share the node coordinates array.
8027  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8028  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8029  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8030  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8031  */
8032 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8033 {
8034   //All checks are delegated to MergeUMeshesOnSameCoords
8035   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8037   corr.resize(meshes.size());
8038   std::size_t nbOfMeshes=meshes.size();
8039   int offset=0;
8040   const int *o2nPtr=o2n->getConstPointer();
8041   for(std::size_t i=0;i<nbOfMeshes;i++)
8042     {
8043       DataArrayInt *tmp=DataArrayInt::New();
8044       int curNbOfCells=meshes[i]->getNumberOfCells();
8045       tmp->alloc(curNbOfCells,1);
8046       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8047       offset+=curNbOfCells;
8048       tmp->setName(meshes[i]->getName());
8049       corr[i]=tmp;
8050     }
8051   return ret.retn();
8052 }
8053
8054 /*!
8055  * Makes all given meshes share the nodal connectivity array. The common connectivity
8056  * array is created by concatenating the connectivity arrays of all given meshes. All
8057  * the given meshes must be of the same space dimension but dimension of cells **can
8058  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8059  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8060  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8061  *  \param [in,out] meshes - a vector of meshes to update.
8062  *  \throw If any of \a meshes is NULL.
8063  *  \throw If the coordinates array is not set in any of \a meshes.
8064  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8065  *  \throw If \a meshes are of different space dimension.
8066  */
8067 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8068 {
8069   std::size_t sz=meshes.size();
8070   if(sz==0 || sz==1)
8071     return;
8072   std::vector< const DataArrayDouble * > coords(meshes.size());
8073   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8074   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8075     {
8076       if((*it))
8077         {
8078           (*it)->checkConnectivityFullyDefined();
8079           const DataArrayDouble *coo=(*it)->getCoords();
8080           if(coo)
8081             *it2=coo;
8082           else
8083             {
8084               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8085               oss << " has no coordinate array defined !";
8086               throw INTERP_KERNEL::Exception(oss.str().c_str());
8087             }
8088         }
8089       else
8090         {
8091           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8092           oss << " is null !";
8093           throw INTERP_KERNEL::Exception(oss.str().c_str());
8094         }
8095     }
8096   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8097   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8098   int offset=(*it)->getNumberOfNodes();
8099   (*it++)->setCoords(res);
8100   for(;it!=meshes.end();it++)
8101     {
8102       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8103       (*it)->setCoords(res);
8104       (*it)->shiftNodeNumbersInConn(offset);
8105       offset+=oldNumberOfNodes;
8106     }
8107 }
8108
8109 /*!
8110  * Merges nodes coincident with a given precision within all given meshes that share
8111  * the nodal connectivity array. The given meshes **can be of different** mesh
8112  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8113  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8114  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8115  *  \param [in,out] meshes - a vector of meshes to update.
8116  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8117  *  \throw If any of \a meshes is NULL.
8118  *  \throw If the \a meshes do not share the same node coordinates array.
8119  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8120  */
8121 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8122 {
8123   if(meshes.empty())
8124     return ;
8125   std::set<const DataArrayDouble *> s;
8126   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8127     {
8128       if(*it)
8129         s.insert((*it)->getCoords());
8130       else
8131         {
8132           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 !";
8133           throw INTERP_KERNEL::Exception(oss.str().c_str());
8134         }
8135     }
8136   if(s.size()!=1)
8137     {
8138       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 !";
8139       throw INTERP_KERNEL::Exception(oss.str().c_str());
8140     }
8141   const DataArrayDouble *coo=*(s.begin());
8142   if(!coo)
8143     return;
8144   //
8145   DataArrayInt *comm,*commI;
8146   coo->findCommonTuples(eps,-1,comm,commI);
8147   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8148   int oldNbOfNodes=coo->getNumberOfTuples();
8149   int newNbOfNodes;
8150   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8151   if(oldNbOfNodes==newNbOfNodes)
8152     return ;
8153   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8154   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8155     {
8156       (*it)->renumberNodesInConn(o2n->getConstPointer());
8157       (*it)->setCoords(newCoords);
8158     } 
8159 }
8160
8161 /*!
8162  * 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.
8163  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8164  * \param isQuad specifies the policy of connectivity.
8165  * @ret in/out parameter in which the result will be append
8166  */
8167 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8168 {
8169   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8170   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8171   ret.push_back(cm.getExtrudedType());
8172   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8173   switch(flatType)
8174   {
8175     case INTERP_KERNEL::NORM_POINT1:
8176       {
8177         ret.push_back(connBg[1]);
8178         ret.push_back(connBg[1]+nbOfNodesPerLev);
8179         break;
8180       }
8181     case INTERP_KERNEL::NORM_SEG2:
8182       {
8183         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8184         ret.insert(ret.end(),conn,conn+4);
8185         break;
8186       }
8187     case INTERP_KERNEL::NORM_SEG3:
8188       {
8189         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8190         ret.insert(ret.end(),conn,conn+8);
8191         break;
8192       }
8193     case INTERP_KERNEL::NORM_QUAD4:
8194       {
8195         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8196         ret.insert(ret.end(),conn,conn+8);
8197         break;
8198       }
8199     case INTERP_KERNEL::NORM_TRI3:
8200       {
8201         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8202         ret.insert(ret.end(),conn,conn+6);
8203         break;
8204       }
8205     case INTERP_KERNEL::NORM_TRI6:
8206       {
8207         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,
8208           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8209         ret.insert(ret.end(),conn,conn+15);
8210         break;
8211       }
8212     case INTERP_KERNEL::NORM_QUAD8:
8213       {
8214         int conn[20]={
8215           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8216           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8217           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8218         };
8219         ret.insert(ret.end(),conn,conn+20);
8220         break;
8221       }
8222     case INTERP_KERNEL::NORM_POLYGON:
8223       {
8224         std::back_insert_iterator< std::vector<int> > ii(ret);
8225         std::copy(connBg+1,connEnd,ii);
8226         *ii++=-1;
8227         std::reverse_iterator<const int *> rConnBg(connEnd);
8228         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8229         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8230         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8231         for(std::size_t i=0;i<nbOfRadFaces;i++)
8232           {
8233             *ii++=-1;
8234             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8235             std::copy(conn,conn+4,ii);
8236           }
8237         break;
8238       }
8239     default:
8240       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8241   }
8242 }
8243
8244 /*!
8245  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8246  */
8247 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8248 {
8249   std::size_t i, ip1;
8250   double v[3]={0.,0.,0.};
8251   std::size_t sz=std::distance(begin,end);
8252   if(isQuadratic)
8253     sz/=2;
8254   for(i=0;i<sz;i++)
8255     {
8256       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];
8257       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8258       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8259     }
8260   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8261
8262   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8263   // SEG3 forming a circle):
8264   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8265     {
8266       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8267       for(std::size_t j=0;j<sz;j++)
8268         {
8269           if (j%2)  // current point i is quadratic, next point i+1 is standard
8270             {
8271               i = sz+j;
8272               ip1 = (j+1)%sz; // ip1 = "i+1"
8273             }
8274           else      // current point i is standard, next point i+1 is quadratic
8275             {
8276               i = j;
8277               ip1 = j+sz;
8278             }
8279           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8280           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8281           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8282         }
8283       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8284     }
8285   return (ret>0.);
8286 }
8287
8288 /*!
8289  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8290  */
8291 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8292 {
8293   std::vector<std::pair<int,int> > edges;
8294   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8295   const int *bgFace=begin;
8296   for(std::size_t i=0;i<nbOfFaces;i++)
8297     {
8298       const int *endFace=std::find(bgFace+1,end,-1);
8299       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8300       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8301         {
8302           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8303           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8304             return false;
8305           edges.push_back(p1);
8306         }
8307       bgFace=endFace+1;
8308     }
8309   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8310 }
8311
8312 /*!
8313  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8314  */
8315 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8316 {
8317   double vec0[3],vec1[3];
8318   std::size_t sz=std::distance(begin,end);
8319   if(sz%2!=0)
8320     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8321   int nbOfNodes=(int)sz/2;
8322   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8323   const double *pt0=coords+3*begin[0];
8324   const double *pt1=coords+3*begin[nbOfNodes];
8325   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8326   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8327 }
8328
8329 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8330 {
8331   std::size_t sz=std::distance(begin,end);
8332   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8333   std::size_t nbOfNodes(sz/2);
8334   std::copy(begin,end,(int *)tmp);
8335   for(std::size_t j=1;j<nbOfNodes;j++)
8336     {
8337       begin[j]=tmp[nbOfNodes-j];
8338       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8339     }
8340 }
8341
8342 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8343 {
8344   std::size_t sz=std::distance(begin,end);
8345   if(sz!=4)
8346     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8347   double vec0[3],vec1[3];
8348   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8349   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]; 
8350   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;
8351 }
8352
8353 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8354 {
8355   std::size_t sz=std::distance(begin,end);
8356   if(sz!=5)
8357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8358   double vec0[3];
8359   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8360   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8361   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8362 }
8363
8364 /*!
8365  * 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 ) 
8366  * 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
8367  * a 2D space.
8368  *
8369  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8370  * \param [in] coords the coordinates with nb of components exactly equal to 3
8371  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8372  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8373  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8374  */
8375 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8376 {
8377   int nbFaces=std::count(begin+1,end,-1)+1;
8378   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8379   double *vPtr=v->getPointer();
8380   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8381   double *pPtr=p->getPointer();
8382   const int *stFaceConn=begin+1;
8383   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8384     {
8385       const int *endFaceConn=std::find(stFaceConn,end,-1);
8386       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8387       stFaceConn=endFaceConn+1;
8388     }
8389   pPtr=p->getPointer(); vPtr=v->getPointer();
8390   DataArrayInt *comm1=0,*commI1=0;
8391   v->findCommonTuples(eps,-1,comm1,commI1);
8392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8393   const int *comm1Ptr=comm1->getConstPointer();
8394   const int *commI1Ptr=commI1->getConstPointer();
8395   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8396   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8397   //
8398   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8399   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8400   mm->finishInsertingCells();
8401   //
8402   for(int i=0;i<nbOfGrps1;i++)
8403     {
8404       int vecId=comm1Ptr[commI1Ptr[i]];
8405       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8406       DataArrayInt *comm2=0,*commI2=0;
8407       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8408       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8409       const int *comm2Ptr=comm2->getConstPointer();
8410       const int *commI2Ptr=commI2->getConstPointer();
8411       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8412       for(int j=0;j<nbOfGrps2;j++)
8413         {
8414           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8415             {
8416               res->insertAtTheEnd(begin,end);
8417               res->pushBackSilent(-1);
8418             }
8419           else
8420             {
8421               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8422               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8423               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8424               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8425               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8426               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8427               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8428               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8429               const int *idsNodePtr=idsNode->getConstPointer();
8430               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];
8431               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8432               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8433               if(std::abs(norm)>eps)
8434                 {
8435                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8436                   mm3->rotate(center,vec,angle);
8437                 }
8438               mm3->changeSpaceDimension(2);
8439               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8440               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8441               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8442               int nbOfCells=mm4->getNumberOfCells();
8443               for(int k=0;k<nbOfCells;k++)
8444                 {
8445                   int l=0;
8446                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8447                     res->pushBackSilent(idsNodePtr[*work]);
8448                   res->pushBackSilent(-1);
8449                 }
8450             }
8451         }
8452     }
8453   res->popBackSilent();
8454 }
8455
8456 /*!
8457  * 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
8458  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8459  * 
8460  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8461  * \param [in] coords coordinates expected to have 3 components.
8462  * \param [in] begin start of the nodal connectivity of the face.
8463  * \param [in] end end of the nodal connectivity (excluded) of the face.
8464  * \param [out] v the normalized vector of size 3
8465  * \param [out] p the pos of plane
8466  */
8467 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8468 {
8469   std::size_t nbPoints=std::distance(begin,end);
8470   if(nbPoints<3)
8471     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8472   double vec[3]={0.,0.,0.};
8473   std::size_t j=0;
8474   bool refFound=false;
8475   for(;j<nbPoints-1 && !refFound;j++)
8476     {
8477       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8478       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8479       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8480       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8481       if(norm>eps)
8482         {
8483           refFound=true;
8484           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8485         }
8486     }
8487   for(std::size_t i=j;i<nbPoints-1;i++)
8488     {
8489       double curVec[3];
8490       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8491       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8492       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8493       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8494       if(norm<eps)
8495         continue;
8496       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8497       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];
8498       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8499       if(norm>eps)
8500         {
8501           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8502           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8503           return ;
8504         }
8505     }
8506   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8507 }
8508
8509 /*!
8510  * This method tries to obtain a well oriented polyhedron.
8511  * If the algorithm fails, an exception will be thrown.
8512  */
8513 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8514 {
8515   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8516   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8517   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8518   isPerm[0]=true;
8519   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8520   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8521   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8522   //
8523   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8524     {
8525       bgFace=begin;
8526       std::size_t smthChanged=0;
8527       for(std::size_t i=0;i<nbOfFaces;i++)
8528         {
8529           endFace=std::find(bgFace+1,end,-1);
8530           nbOfEdgesInFace=std::distance(bgFace,endFace);
8531           if(!isPerm[i])
8532             {
8533               bool b;
8534               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8535                 {
8536                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8537                   std::pair<int,int> p2(p1.second,p1.first);
8538                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8539                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8540                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8541                 }
8542               if(isPerm[i])
8543                 { 
8544                   if(!b)
8545                     std::reverse(bgFace+1,endFace);
8546                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8547                     {
8548                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8549                       std::pair<int,int> p2(p1.second,p1.first);
8550                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8551                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8552                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8553                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8554                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8555                       if(it!=edgesOK.end())
8556                         {
8557                           edgesOK.erase(it);
8558                           edgesFinished.push_back(p1);
8559                         }
8560                       else
8561                         edgesOK.push_back(p1);
8562                     }
8563                 }
8564             }
8565           bgFace=endFace+1;
8566         }
8567       if(smthChanged==0)
8568         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8569     }
8570   if(!edgesOK.empty())
8571     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8572   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8573     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8574       bgFace=begin;
8575       for(std::size_t i=0;i<nbOfFaces;i++)
8576         {
8577           endFace=std::find(bgFace+1,end,-1);
8578           std::reverse(bgFace+1,endFace);
8579           bgFace=endFace+1;
8580         }
8581     }
8582 }
8583
8584 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8585 {
8586   int nbOfNodesExpected(skin->getNumberOfNodes());
8587   const int *n2oPtr(n2o->getConstPointer());
8588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8589   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8590   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8591   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8592   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8593   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8594   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8595   if(nbOfNodesExpected<1)
8596     return ret.retn();
8597   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8598   *work++=n2oPtr[prevNode];
8599   for(int i=1;i<nbOfNodesExpected;i++)
8600     {
8601       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8602         {
8603           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8604           conn.erase(prevNode);
8605           if(conn.size()==1)
8606             {
8607               int curNode(*(conn.begin()));
8608               *work++=n2oPtr[curNode];
8609               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8610               shar.erase(prevCell);
8611               if(shar.size()==1)
8612                 {
8613                   prevCell=*(shar.begin());
8614                   prevNode=curNode;
8615                 }
8616               else
8617                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8618             }
8619           else
8620             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8621         }
8622       else
8623         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8624     }
8625   return ret.retn();
8626 }
8627
8628 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8629 {
8630   int nbOfNodesExpected(skin->getNumberOfNodes());
8631   int nbOfTurn(nbOfNodesExpected/2);
8632   const int *n2oPtr(n2o->getConstPointer());
8633   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8634   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8635   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8636   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8637   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8639   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8640   if(nbOfNodesExpected<1)
8641     return ret.retn();
8642   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8643   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8644   for(int i=1;i<nbOfTurn;i++)
8645     {
8646       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8647         {
8648           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8649           conn.erase(prevNode);
8650           if(conn.size()==1)
8651             {
8652               int curNode(*(conn.begin()));
8653               *work=n2oPtr[curNode];
8654               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8655               shar.erase(prevCell);
8656               if(shar.size()==1)
8657                 {
8658                   int curCell(*(shar.begin()));
8659                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8660                   prevCell=curCell;
8661                   prevNode=curNode;
8662                   work++;
8663                 }
8664               else
8665                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8666             }
8667           else
8668             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8669         }
8670       else
8671         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8672     }
8673   return ret.retn();
8674 }
8675
8676 /*!
8677  * This method makes the assumption spacedimension == meshdimension == 2.
8678  * This method works only for linear cells.
8679  * 
8680  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8681  */
8682 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8683 {
8684   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8686   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8687   int oldNbOfNodes(skin->getNumberOfNodes());
8688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8689   int nbOfNodesExpected(skin->getNumberOfNodes());
8690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8691   int nbCells(skin->getNumberOfCells());
8692   if(nbCells==nbOfNodesExpected)
8693     return buildUnionOf2DMeshLinear(skin,n2o);
8694   else if(2*nbCells==nbOfNodesExpected)
8695     return buildUnionOf2DMeshQuadratic(skin,n2o);
8696   else
8697     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8698 }
8699
8700 /*!
8701  * This method makes the assumption spacedimension == meshdimension == 3.
8702  * This method works only for linear cells.
8703  * 
8704  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8705  */
8706 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8707 {
8708   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8710   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8711   const int *conn=m->getNodalConnectivity()->getConstPointer();
8712   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8713   int nbOfCells=m->getNumberOfCells();
8714   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8715   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8716   if(nbOfCells<1)
8717     return ret.retn();
8718   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8719   for(int i=1;i<nbOfCells;i++)
8720     {
8721       *work++=-1;
8722       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8723     }
8724   return ret.retn();
8725 }
8726
8727 /*!
8728  * \brief Creates a graph of cell neighbors
8729  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8730  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8731  *  For example
8732  *  - index:  0 3 5 6 6
8733  *  - value:  1 2 3 2 3 3
8734  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8735  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8736  */
8737 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8738 {
8739   checkConnectivityFullyDefined();
8740
8741   int meshDim = this->getMeshDimension();
8742   ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8743   ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8744   this->getReverseNodalConnectivity(revConn,indexr);
8745   const int* indexr_ptr=indexr->getConstPointer();
8746   const int* revConn_ptr=revConn->getConstPointer();
8747
8748   const ParaMEDMEM::DataArrayInt* index;
8749   const ParaMEDMEM::DataArrayInt* conn;
8750   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8751   index=this->getNodalConnectivityIndex();
8752   int nbCells=this->getNumberOfCells();
8753   const int* index_ptr=index->getConstPointer();
8754   const int* conn_ptr=conn->getConstPointer();
8755
8756   //creating graph arcs (cell to cell relations)
8757   //arcs are stored in terms of (index,value) notation
8758   // 0 3 5 6 6
8759   // 1 2 3 2 3 3
8760   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8761   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8762
8763   //warning here one node have less than or equal effective number of cell with it
8764   //but cell could have more than effective nodes
8765   //because other equals nodes in other domain (with other global inode)
8766   std::vector <int> cell2cell_index(nbCells+1,0);
8767   std::vector <int> cell2cell;
8768   cell2cell.reserve(3*nbCells);
8769
8770   for (int icell=0; icell<nbCells;icell++)
8771     {
8772       std::map<int,int > counter;
8773       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8774         {
8775           int inode=conn_ptr[iconn];
8776           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8777             {
8778               int icell2=revConn_ptr[iconnr];
8779               std::map<int,int>::iterator iter=counter.find(icell2);
8780               if (iter!=counter.end()) (iter->second)++;
8781               else counter.insert(std::make_pair(icell2,1));
8782             }
8783         }
8784       for (std::map<int,int>::const_iterator iter=counter.begin();
8785            iter!=counter.end(); iter++)
8786         if (iter->second >= meshDim)
8787           {
8788             cell2cell_index[icell+1]++;
8789             cell2cell.push_back(iter->first);
8790           }
8791     }
8792   indexr->decrRef();
8793   revConn->decrRef();
8794   cell2cell_index[0]=0;
8795   for (int icell=0; icell<nbCells;icell++)
8796     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8797
8798   //filling up index and value to create skylinearray structure
8799   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8800   return array;
8801 }
8802
8803 /*!
8804  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8805  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8806  */
8807 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8808 {
8809   double *w=zipFrmt;
8810   if(spaceDim==3)
8811     for(int i=0;i<nbOfNodesInCell;i++)
8812       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8813   else if(spaceDim==2)
8814     {
8815       for(int i=0;i<nbOfNodesInCell;i++)
8816         {
8817           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8818           *w++=0.;
8819         }
8820     }
8821   else
8822     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8823 }
8824
8825 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8826 {
8827   int nbOfCells=getNumberOfCells();
8828   if(nbOfCells<=0)
8829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8830   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};
8831   ofs << "  <" << getVTKDataSetType() << ">\n";
8832   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8833   ofs << "      <PointData>\n" << pointData << std::endl;
8834   ofs << "      </PointData>\n";
8835   ofs << "      <CellData>\n" << cellData << std::endl;
8836   ofs << "      </CellData>\n";
8837   ofs << "      <Points>\n";
8838   if(getSpaceDimension()==3)
8839     _coords->writeVTK(ofs,8,"Points",byteData);
8840   else
8841     {
8842       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8843       coo->writeVTK(ofs,8,"Points",byteData);
8844     }
8845   ofs << "      </Points>\n";
8846   ofs << "      <Cells>\n";
8847   const int *cPtr=_nodal_connec->getConstPointer();
8848   const int *cIPtr=_nodal_connec_index->getConstPointer();
8849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8851   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8852   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8853   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8854   int szFaceOffsets=0,szConn=0;
8855   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8856     {
8857       *w2=cPtr[cIPtr[i]];
8858       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8859         {
8860           *w1=-1;
8861           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8862           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8863         }
8864       else
8865         {
8866           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8867           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8868           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8869           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8870           w4=std::copy(c.begin(),c.end(),w4);
8871         }
8872     }
8873   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8874   types->writeVTK(ofs,8,"UInt8","types",byteData);
8875   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8876   if(szFaceOffsets!=0)
8877     {//presence of Polyhedra
8878       connectivity->reAlloc(szConn);
8879       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8880       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8881       w1=faces->getPointer();
8882       for(int i=0;i<nbOfCells;i++)
8883         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8884           {
8885             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8886             *w1++=nbFaces;
8887             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8888             for(int j=0;j<nbFaces;j++)
8889               {
8890                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8891                 *w1++=(int)std::distance(w6,w5);
8892                 w1=std::copy(w6,w5,w1);
8893                 w6=w5+1;
8894               }
8895           }
8896       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8897     }
8898   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8899   ofs << "      </Cells>\n";
8900   ofs << "    </Piece>\n";
8901   ofs << "  </" << getVTKDataSetType() << ">\n";
8902 }
8903
8904 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8905 {
8906   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8907   if(_mesh_dim==-2)
8908     { stream << " Not set !"; return ; }
8909   stream << " Mesh dimension : " << _mesh_dim << ".";
8910   if(_mesh_dim==-1)
8911     return ;
8912   if(!_coords)
8913     { stream << " No coordinates set !"; return ; }
8914   if(!_coords->isAllocated())
8915     { stream << " Coordinates set but not allocated !"; return ; }
8916   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8917   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8918   if(!_nodal_connec_index)
8919     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8920   if(!_nodal_connec_index->isAllocated())
8921     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8922   int lgth=_nodal_connec_index->getNumberOfTuples();
8923   int cpt=_nodal_connec_index->getNumberOfComponents();
8924   if(cpt!=1 || lgth<1)
8925     return ;
8926   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8927 }
8928
8929 std::string MEDCouplingUMesh::getVTKDataSetType() const
8930 {
8931   return std::string("UnstructuredGrid");
8932 }
8933
8934 std::string MEDCouplingUMesh::getVTKFileExtension() const
8935 {
8936   return std::string("vtu");
8937 }
8938
8939 /*!
8940  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8941  * returns a result mesh constituted by polygons.
8942  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8943  * all nodes from m2.
8944  * The meshes should be in 2D space. In
8945  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8946  * meshes.
8947  *  \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
8948  *                      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)
8949  *  \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
8950  *                      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)
8951  *  \param [in] eps - precision used to detect coincident mesh entities.
8952  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8953  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8954  *         this array using decrRef() as it is no more needed.
8955  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8956  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8957  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8958  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8959  *         it is no more needed.  
8960  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8961  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8962  *         is no more needed.  
8963  *  \throw If the coordinates array is not set in any of the meshes.
8964  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8965  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8966  *
8967  *  \sa conformize2D, mergeNodes
8968  */
8969 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8970                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8971 {
8972   if(!m1 || !m2)
8973     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8974   m1->checkFullyDefined();
8975   m2->checkFullyDefined();
8976   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8977     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8978
8979   // Step 1: compute all edge intersections (new nodes)
8980   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8981   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8982   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8983   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8984   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8985                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8986                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8987   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8989   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8990
8991   // Step 2: re-order newly created nodes according to the ordering found in m2
8992   std::vector< std::vector<int> > intersectEdge2;
8993   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8994   subDiv2.clear(); dd5=0; dd6=0;
8995
8996   // Step 3:
8997   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8998   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8999   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9000                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9001
9002   // Step 4: Prepare final result:
9003   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9004   addCooDa->alloc((int)(addCoo.size())/2,2);
9005   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9006   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9007   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9008   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9009   std::vector<const DataArrayDouble *> coordss(4);
9010   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9011   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9012   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9013   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9017   ret->setConnectivity(conn,connI,true);
9018   ret->setCoords(coo);
9019   cellNb1=c1.retn(); cellNb2=c2.retn();
9020   return ret.retn();
9021 }
9022
9023 /// @cond INTERNAL
9024
9025 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9026 {
9027   if(candidates.empty())
9028     return false;
9029   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9030     {
9031       const std::vector<int>& pool(intersectEdge1[*it]);
9032       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9033       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9034         {
9035           retVal=*it+1;
9036           return true;
9037         }
9038       tmp[0]=stop; tmp[1]=start;
9039       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9040         {
9041           retVal=-*it-1;
9042           return true;
9043         }
9044     }
9045   return false;
9046 }
9047
9048 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,
9049                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9050 {
9051   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9052   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9053   int nCells(mesh1D->getNumberOfCells());
9054   if(nCells!=(int)intersectEdge2.size())
9055     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9056   const DataArrayDouble *coo2(mesh1D->getCoords());
9057   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9058   const double *coo2Ptr(coo2->begin());
9059   int offset1(coords1->getNumberOfTuples());
9060   int offset2(offset1+coo2->getNumberOfTuples());
9061   int offset3(offset2+addCoo.size()/2);
9062   std::vector<double> addCooQuad;
9063   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9064   int tmp[4],cicnt(0),kk(0);
9065   for(int i=0;i<nCells;i++)
9066     {
9067       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9068       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9069       const std::vector<int>& subEdges(intersectEdge2[i]);
9070       int nbSubEdge(subEdges.size()/2);
9071       for(int j=0;j<nbSubEdge;j++,kk++)
9072         {
9073           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));
9074           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9075           INTERP_KERNEL::Edge *e2Ptr(e2);
9076           std::map<int,int>::const_iterator itm;
9077           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9078             {
9079               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9080               itm=mergedNodes.find(subEdges[2*j]);
9081               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9082               itm=mergedNodes.find(subEdges[2*j+1]);
9083               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9084               tmp[3]=offset3+(int)addCooQuad.size()/2;
9085               double tmp2[2];
9086               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9087               cicnt+=4;
9088               cOut->insertAtTheEnd(tmp,tmp+4);
9089               ciOut->pushBackSilent(cicnt);
9090             }
9091           else
9092             {
9093               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9094               itm=mergedNodes.find(subEdges[2*j]);
9095               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9096               itm=mergedNodes.find(subEdges[2*j+1]);
9097               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9098               cicnt+=3;
9099               cOut->insertAtTheEnd(tmp,tmp+3);
9100               ciOut->pushBackSilent(cicnt);
9101             }
9102           int tmp00;
9103           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9104             {
9105               idsInRetColinear->pushBackSilent(kk);
9106               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9107             }
9108         }
9109       e->decrRef();
9110     }
9111   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9112   ret->setConnectivity(cOut,ciOut,true);
9113   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9114   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9115   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9116   std::vector<const DataArrayDouble *> coordss(4);
9117   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9118   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9119   ret->setCoords(arr);
9120   return ret.retn();
9121 }
9122
9123 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9124 {
9125   std::vector<int> allEdges;
9126   for(const int *it2(descBg);it2!=descEnd;it2++)
9127     {
9128       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9129       if(*it2>0)
9130         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9131       else
9132         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9133     }
9134   std::size_t nb(allEdges.size());
9135   if(nb%2!=0)
9136     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9137   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9138   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9139   ret->setCoords(coords);
9140   ret->allocateCells(1);
9141   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9142   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9143     connOut[kk]=allEdges[2*kk];
9144   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9145   return ret.retn();
9146 }
9147
9148 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9149 {
9150   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9151   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9152   std::size_t ii(0);
9153   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9154   if(sz!=std::distance(descBg,descEnd))
9155     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9156   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9157   std::vector<int> allEdges,centers;
9158   const double *coordsPtr(coords->begin());
9159   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9160   int offset(coords->getNumberOfTuples());
9161   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9162     {
9163       INTERP_KERNEL::NormalizedCellType typeOfSon;
9164       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9165       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9166       if(*it2>0)
9167         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9168       else
9169         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9170       if(edge1.size()==2)
9171         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9172       else
9173         {//the current edge has been subsplit -> create corresponding centers.
9174           std::size_t nbOfCentersToAppend(edge1.size()/2);
9175           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9176           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9177           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9178           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9179             {
9180               double tmpp[2];
9181               const double *aa(coordsPtr+2*(*it3++));
9182               const double *bb(coordsPtr+2*(*it3++));
9183               ee->getMiddleOfPoints(aa,bb,tmpp);
9184               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9185               centers.push_back(offset+k);
9186             }
9187         }
9188     }
9189   std::size_t nb(allEdges.size());
9190   if(nb%2!=0)
9191     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9192   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9193   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9194   if(addCoo->empty())
9195     ret->setCoords(coords);
9196   else
9197     {
9198       addCoo->rearrange(2);
9199       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9200       ret->setCoords(addCoo);
9201     }
9202   ret->allocateCells(1);
9203   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9204   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9205     connOut[kk]=allEdges[2*kk];
9206   connOut.insert(connOut.end(),centers.begin(),centers.end());
9207   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9208   return ret.retn();
9209 }
9210
9211 /*!
9212  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9213  * of those edges.
9214  *
9215  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9216  */
9217 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9218 {
9219   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9220   if(!cm.isQuadratic())
9221     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9222   else
9223     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9224 }
9225
9226 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9227 {
9228   bool isQuad(false);
9229   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9230     {
9231       const INTERP_KERNEL::Edge *ee(*it);
9232       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9233         isQuad=true;
9234     }
9235   if(!isQuad)
9236     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9237   else
9238     {
9239       const double *coo(mesh2D->getCoords()->begin());
9240       std::size_t sz(conn.size());
9241       std::vector<double> addCoo;
9242       std::vector<int> conn2(conn);
9243       int offset(mesh2D->getNumberOfNodes());
9244       for(std::size_t i=0;i<sz;i++)
9245         {
9246           double tmp[2];
9247           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9248           addCoo.insert(addCoo.end(),tmp,tmp+2);
9249           conn2.push_back(offset+(int)i);
9250         }
9251       mesh2D->getCoords()->rearrange(1);
9252       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9253       mesh2D->getCoords()->rearrange(2);
9254       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9255     }
9256 }
9257
9258 /*!
9259  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9260  *
9261  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9262  * a set of edges defined in \a splitMesh1D.
9263  */
9264 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9265                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9266 {
9267   std::size_t nb(edge1Bis.size()/2);
9268   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9269   int iEnd(splitMesh1D->getNumberOfCells());
9270   if(iEnd==0)
9271     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9272   std::size_t ii,jj;
9273   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9274   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9275   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9276   //
9277   if(jj==nb)
9278     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9279       out0.resize(1); out1.resize(1);
9280       std::vector<int>& connOut(out0[0]);
9281       connOut.resize(nbOfEdgesOf2DCellSplit);
9282       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9283       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9284       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9285         {
9286           connOut[kk]=edge1Bis[2*kk];
9287           edgesPtr[kk]=edge1BisPtr[2*kk];
9288         }
9289     }
9290   else
9291     {
9292       // [i,iEnd[ contains the
9293       out0.resize(2); out1.resize(2);
9294       std::vector<int>& connOutLeft(out0[0]);
9295       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9296       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9297       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9298       for(std::size_t k=ii;k<jj+1;k++)
9299         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9300       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9301       for(int ik=0;ik<iEnd;ik++)
9302         {
9303           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9304           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9305           ees[ik]=ee;
9306         }
9307       for(int ik=iEnd-1;ik>=0;ik--)
9308         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9309       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9310         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9311       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9312       for(int ik=0;ik<iEnd;ik++)
9313         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9314       eright.insert(eright.end(),ees.begin(),ees.end());
9315     }
9316 }
9317
9318 /// @endcond
9319
9320 /// @cond INTERNAL
9321
9322 struct CellInfo
9323 {
9324 public:
9325   CellInfo() { }
9326   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9327 public:
9328   std::vector<int> _edges;
9329   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9330 };
9331
9332 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9333 {
9334   std::size_t nbe(edges.size());
9335   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9336   for(std::size_t i=0;i<nbe;i++)
9337     {
9338       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9339       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9340     }
9341   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9342   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9343   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9344 }
9345
9346 class EdgeInfo
9347 {
9348 public:
9349   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9350   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9351   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9352   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9353   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9354 private:
9355   int _istart;
9356   int _iend;
9357   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9358   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9359   int _left;
9360   int _right;
9361 };
9362
9363 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9364 {
9365   const MEDCouplingUMesh *mesh(_mesh);
9366   if(mesh)
9367     return ;
9368   if(_right<pos)
9369     return ;
9370   if(_left>pos)
9371     { _left++; _right++; return ; }
9372   if(_right==pos)
9373     {
9374       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9375       if((isLeft && isRight) || (!isLeft && !isRight))
9376         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9377       if(isLeft)
9378         return ;
9379       if(isRight)
9380         {
9381           _right++;
9382           return ;
9383         }
9384     }
9385   if(_left==pos)
9386     {
9387       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9388       if((isLeft && isRight) || (!isLeft && !isRight))
9389         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9390       if(isLeft)
9391         {
9392           _right++;
9393           return ;
9394         }
9395       if(isRight)
9396         {
9397           _left++;
9398           _right++;
9399           return ;
9400         }
9401     }
9402 }
9403
9404 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9405 {
9406   const MEDCouplingUMesh *mesh(_mesh);
9407   if(!mesh)
9408     {
9409       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9410     }
9411   else
9412     {// not fully splitting cell case
9413       if(mesh2D->getNumberOfCells()==1)
9414         {//little optimization. 1 cell no need to find in which cell mesh is !
9415           neighbors[0]=offset; neighbors[1]=offset;
9416           return;
9417         }
9418       else
9419         {
9420           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9421           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9422           if(cellId==-1)
9423             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9424           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9425         }
9426     }
9427 }
9428
9429 class VectorOfCellInfo
9430 {
9431 public:
9432   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9433   std::size_t size() const { return _pool.size(); }
9434   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9435   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);
9436   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9437   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9438   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9439   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9440 private:
9441   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9442   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9443   const CellInfo& get(int pos) const;
9444   CellInfo& get(int pos);
9445 private:
9446   std::vector<CellInfo> _pool;
9447   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9448   std::vector<EdgeInfo> _edge_info;
9449 };
9450
9451 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9452 {
9453   _pool[0]._edges=edges;
9454   _pool[0]._edges_ptr=edgesPtr;
9455 }
9456
9457 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9458 {
9459   if(_pool.empty())
9460     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9461   if(_pool.size()==1)
9462     return 0;
9463   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9464   if(!zeMesh)
9465     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9466   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9467   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9468 }
9469
9470 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)
9471 {
9472   get(pos);//to check pos
9473   bool isFast(pos==0 && _pool.size()==1);
9474   std::size_t sz(edges.size());
9475   // dealing with edges
9476   if(sz==1)
9477     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9478   else
9479     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9480   //
9481   std::vector<CellInfo> pool(_pool.size()-1+sz);
9482   for(int i=0;i<pos;i++)
9483     pool[i]=_pool[i];
9484   for(std::size_t j=0;j<sz;j++)
9485     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9486   for(int i=pos+1;i<(int)_pool.size();i++)
9487     pool[i+sz-1]=_pool[i];
9488   _pool=pool;
9489   //
9490   if(sz==2)
9491     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9492   //
9493   if(isFast)
9494     {
9495       _ze_mesh=mesh;
9496       return ;
9497     }
9498   //
9499   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9500   if(pos>0)
9501     {
9502       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9503       ms.push_back(elt);
9504     }
9505   ms.push_back(mesh);
9506   if(pos<_ze_mesh->getNumberOfCells()-1)
9507   {
9508     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9509     ms.push_back(elt);
9510   }
9511   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9512   for(std::size_t j=0;j<ms2.size();j++)
9513     ms2[j]=ms[j];
9514   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9515 }
9516
9517 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9518 {
9519   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9520 }
9521
9522 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9523 {
9524   if(pos<0)
9525     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9526   int ret(0);
9527   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9528     {
9529       if((*it).isInMyRange(pos))
9530         return ret;
9531     }
9532   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9533 }
9534
9535 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9536 {
9537   get(pos);//to check;
9538   if(_edge_info.empty())
9539     return ;
9540   std::size_t sz(_edge_info.size()-1);
9541   for(std::size_t i=0;i<sz;i++)
9542     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9543 }
9544
9545 const CellInfo& VectorOfCellInfo::get(int pos) const
9546 {
9547   if(pos<0 || pos>=(int)_pool.size())
9548     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9549   return _pool[pos];
9550 }
9551
9552 CellInfo& VectorOfCellInfo::get(int pos)
9553 {
9554   if(pos<0 || pos>=(int)_pool.size())
9555     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9556   return _pool[pos];
9557 }
9558
9559 /*!
9560  * Given :
9561  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9562  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9563  *
9564  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9565  *
9566  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9567  *
9568  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9569  */
9570 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9571                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9572 {
9573   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9574   if(nbCellsInSplitMesh1D==0)
9575     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9576   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9577   std::size_t nb(allEdges.size()),jj;
9578   if(nb%2!=0)
9579     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9580   std::vector<int> edge1Bis(nb*2);
9581   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9582   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9583   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9584   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9585   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9586   //
9587   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9588   int *idsLeftRightPtr(idsLeftRight->getPointer());
9589   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9590   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9591     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9592       int iEnd(iStart);
9593       for(;iEnd<nbCellsInSplitMesh1D;)
9594         {
9595           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9596           if(jj!=nb)
9597             break;
9598           else
9599             iEnd++;
9600         }
9601       if(iEnd<nbCellsInSplitMesh1D)
9602         iEnd++;
9603       //
9604       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9605       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9606       //
9607       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9608       retTmp->setCoords(splitMesh1D->getCoords());
9609       retTmp->allocateCells();
9610
9611       std::vector< std::vector<int> > out0;
9612       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9613
9614       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9615       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9616         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9617       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9618       //
9619       iStart=iEnd;
9620     }
9621   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9622     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9623   return pool.getZeMesh().retn();
9624 }
9625
9626 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9627                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9628                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9629 {
9630   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9631   //
9632   std::vector<int> allEdges;
9633   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9634   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9635     {
9636       int edgeId(std::abs(*it)-1);
9637       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9638       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9639       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9640       if(*it>0)
9641         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9642       else
9643         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9644       std::size_t sz(edge1.size());
9645       for(std::size_t cnt=0;cnt<sz;cnt++)
9646         allEdgesPtr.push_back(ee);
9647     }
9648   //
9649   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9650 }
9651
9652 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9653 {
9654   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9655     {//easy case comparison not
9656       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9657     }
9658   else if(typ1.isQuadratic() && typ2.isQuadratic())
9659     {
9660       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9661       if(!status0)
9662         return false;
9663       if(conn1[2]==conn2[2])
9664         return true;
9665       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9666       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9667       return dist<eps;
9668     }
9669   else
9670     {//only one is quadratic
9671       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9672       if(!status0)
9673         return false;
9674       const double *a(0),*bb(0),*be(0);
9675       if(typ1.isQuadratic())
9676         {
9677           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9678         }
9679       else
9680         {
9681           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9682         }
9683       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9684       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9685       return dist<eps;
9686     }
9687 }
9688
9689 /*!
9690  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9691  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9692  *
9693  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9694  */
9695 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9696 {
9697   if(candidatesIn2DEnd==candidatesIn2DBg)
9698     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9699   const double *coo(mesh2DSplit->getCoords()->begin());
9700   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9701     return *candidatesIn2DBg;
9702   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9703   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9704   if(cellIdInMesh1DSplitRelative<0)
9705     cur1D->changeOrientationOfCells();
9706   const int *c1D(cur1D->getNodalConnectivity()->begin());
9707   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9708   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9709     {
9710       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9711       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9712       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9713       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9714       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9715       for(unsigned it2=0;it2<sz;it2++)
9716         {
9717           INTERP_KERNEL::NormalizedCellType typeOfSon;
9718           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9719           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9720           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9721             return *it;
9722         }
9723     }
9724   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9725 }
9726
9727 /// @endcond
9728
9729 /*!
9730  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9731  * 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
9732  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9733  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9734  *
9735  * \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
9736  *                      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)
9737  * \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
9738  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9739  * \param [in] eps - precision used to perform intersections and localization operations.
9740  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9741  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9742  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9743  *                               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.
9744  * \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
9745  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9746  *                               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.
9747  *
9748  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9749  */
9750 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9751 {
9752   if(!mesh2D || !mesh1D)
9753     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9754   mesh2D->checkFullyDefined();
9755   mesh1D->checkFullyDefined();
9756   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9757   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9759   // Step 1: compute all edge intersections (new nodes)
9760   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9761   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9762   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9763   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9764   //
9765   // Build desc connectivity
9766   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9767   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9768   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9769   std::map<int,int> mergedNodes;
9770   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9771   // use mergeNodes to fix intersectEdge1
9772   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9773     {
9774       std::size_t n((*it0).size()/2);
9775       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9776       std::map<int,int>::const_iterator it1;
9777       it1=mergedNodes.find(eltStart);
9778       if(it1!=mergedNodes.end())
9779         (*it0)[0]=(*it1).second;
9780       it1=mergedNodes.find(eltEnd);
9781       if(it1!=mergedNodes.end())
9782         (*it0)[2*n-1]=(*it1).second;
9783     }
9784   //
9785   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9786   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9787   // Step 2: re-order newly created nodes according to the ordering found in m2
9788   std::vector< std::vector<int> > intersectEdge2;
9789   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9790   subDiv2.clear();
9791   // Step 3: compute splitMesh1D
9792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9793   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9794   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9795       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9798   // deal with cells in mesh2D that are not cut but only some of their edges are
9799   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9800   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9801   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9802   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
9803   if(!idsInDesc2DToBeRefined->empty())
9804     {
9805       DataArrayInt *out0(0),*outi0(0);
9806       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9807       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9808       out0s=out0;
9809       out0s=out0s->buildUnique();
9810       out0s->sort(true);
9811     }
9812   //
9813   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9814   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9816   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9819   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9820     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9823   if((DataArrayInt *)out0s)
9824     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9825   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9826   // OK all is ready to insert in ret2 mesh
9827   if(!untouchedCells->empty())
9828     {// the most easy part, cells in mesh2D not impacted at all
9829       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9830       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9831       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9832     }
9833   if((DataArrayInt *)out0s)
9834     {// here dealing with cells in out0s but not in cellsToBeModified
9835       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9836       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9837       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9838         {
9839           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9840           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9841         }
9842       int offset(ret2->getNumberOfTuples());
9843       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9844       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9845       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9846       int kk(0),*ret3ptr(partOfRet3->getPointer());
9847       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9848         {
9849           int faceId(std::abs(*it)-1);
9850           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9851             {
9852               int tmp(fewModifiedCells->locateValue(*it2));
9853               if(tmp!=-1)
9854                 {
9855                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9856                     ret3ptr[2*kk]=tmp+offset;
9857                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9858                     ret3ptr[2*kk+1]=tmp+offset;
9859                 }
9860               else
9861                 {//the current edge is shared by a 2D cell that will be split just after
9862                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9863                     ret3ptr[2*kk]=-(*it2+1);
9864                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9865                     ret3ptr[2*kk+1]=-(*it2+1);
9866                 }
9867             }
9868         }
9869       m1Desc->setCoords(ret1->getCoords());
9870       ret1NonCol->setCoords(ret1->getCoords());
9871       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9872       if(!outMesh2DSplit.empty())
9873         {
9874           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9875           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9876             (*itt)->setCoords(da);
9877         }
9878     }
9879   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9880   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9881     {
9882       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9883       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9884       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9885       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9886       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9887       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));
9888       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9889       outMesh2DSplit.push_back(splitOfOneCell);
9890       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9891         ret2->pushBackSilent(*it);
9892     }
9893   //
9894   std::size_t nbOfMeshes(outMesh2DSplit.size());
9895   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9896   for(std::size_t i=0;i<nbOfMeshes;i++)
9897     tmp[i]=outMesh2DSplit[i];
9898   //
9899   ret1->getCoords()->setInfoOnComponents(compNames);
9900   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9901   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9902   ret3->rearrange(1);
9903   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9904   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9905     {
9906       int old2DCellId(-ret3->getIJ(*it,0)-1);
9907       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9908       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
9909     }
9910   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9911   ret3->rearrange(2);
9912   //
9913   splitMesh1D=ret1.retn();
9914   splitMesh2D=ret2D.retn();
9915   cellIdInMesh2D=ret2.retn();
9916   cellIdInMesh1D=ret3.retn();
9917 }
9918
9919 /**
9920  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9921  * (newly created) nodes corresponding to the edge intersections.
9922  * Output params:
9923  * @param[out] cr, crI connectivity of the resulting mesh
9924  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9925  * TODO: describe input parameters
9926  */
9927 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9928                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9929                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9930                                                          const std::vector<double>& addCoords,
9931                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9932 {
9933   static const int SPACEDIM=2;
9934   const double *coo1(m1->getCoords()->getConstPointer());
9935   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9936   int offset1(m1->getNumberOfNodes());
9937   const double *coo2(m2->getCoords()->getConstPointer());
9938   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9939   int offset2(offset1+m2->getNumberOfNodes());
9940   int offset3(offset2+((int)addCoords.size())/2);
9941   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9942   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9943   // Here a BBTree on 2D-cells, not on segments:
9944   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9945   int ncell1(m1->getNumberOfCells());
9946   crI.push_back(0);
9947   for(int i=0;i<ncell1;i++)
9948     {
9949       std::vector<int> candidates2;
9950       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9951       std::map<INTERP_KERNEL::Node *,int> mapp;
9952       std::map<int,INTERP_KERNEL::Node *> mappRev;
9953       INTERP_KERNEL::QuadraticPolygon pol1;
9954       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9955       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9956       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9957       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9958       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9959       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9960           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9961       //
9962       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
9963       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9964       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9965       for(it1.first();!it1.finished();it1.next())
9966         edges1.insert(it1.current()->getPtr());
9967       //
9968       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9969       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9970       int ii=0;
9971       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9972         {
9973           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9974           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9975           // Complete mapping with elements coming from the current cell it2 in mesh2:
9976           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9977           // pol2 is the new QP in the final merged result.
9978           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9979               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9980         }
9981       ii=0;
9982       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9983         {
9984           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9985           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9986           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9987           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9988         }
9989       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9990       // by m2 but that we still want to keep in the final result.
9991       if(!edges1.empty())
9992         {
9993           try
9994           {
9995               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9996           }
9997           catch(INTERP_KERNEL::Exception& e)
9998           {
9999               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();
10000               throw INTERP_KERNEL::Exception(oss.str().c_str());
10001           }
10002         }
10003       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10004         (*it).second->decrRef();
10005     }
10006 }
10007
10008 /**
10009  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10010  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10011  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10012  * The caller is to deal with the resulting DataArrayInt.
10013  *  \throw If the coordinate array is not set.
10014  *  \throw If the nodal connectivity of the cells is not defined.
10015  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10016  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10017  *
10018  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10019  */
10020 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10021 {
10022   checkFullyDefined();
10023   if(getMeshDimension()!=1)
10024     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10025
10026   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10027   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10028   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10029   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10030   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10031   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10032   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10033   const int * dsi(_dsi->getConstPointer());
10034   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10035   m_points=0;
10036   if (dsii->getNumberOfTuples())
10037     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10038
10039   int nc(getNumberOfCells());
10040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10041   result->alloc(nc,1);
10042
10043   // set of edges not used so far
10044   std::set<int> edgeSet;
10045   for (int i=0; i<nc; edgeSet.insert(i), i++);
10046
10047   int startSeg=0;
10048   int newIdx=0;
10049   // while we have points with only one neighbor segments
10050   do
10051     {
10052       std::list<int> linePiece;
10053       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10054       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10055         {
10056           // Fill the list forward (resp. backward) from the start segment:
10057           int activeSeg = startSeg;
10058           int prevPointId = -20;
10059           int ptId;
10060           while (!edgeSet.empty())
10061             {
10062               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10063                 {
10064                   if (direction==0)
10065                     linePiece.push_back(activeSeg);
10066                   else
10067                     linePiece.push_front(activeSeg);
10068                   edgeSet.erase(activeSeg);
10069                 }
10070
10071               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10072               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10073               if (dsi[ptId] == 1) // hitting the end of the line
10074                 break;
10075               prevPointId = ptId;
10076               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10077               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10078             }
10079         }
10080       // Done, save final piece into DA:
10081       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10082       newIdx += linePiece.size();
10083
10084       // identify next valid start segment (one which is not consumed)
10085       if(!edgeSet.empty())
10086         startSeg = *(edgeSet.begin());
10087     }
10088   while (!edgeSet.empty());
10089   return result.retn();
10090 }
10091
10092 /// @cond INTERNAL
10093
10094 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10095 {
10096   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10097   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10098   if(it==m.end())
10099     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10100   int v((*it).second);
10101   if(v==forbVal0 || v==forbVal1)
10102     return ;
10103   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10104     isect.push_back(v);
10105 }
10106
10107 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10108 {
10109   int sz(c.size());
10110   if(sz<=1)
10111     return false;
10112   bool presenceOfOn(false);
10113   for(int i=0;i<sz;i++)
10114     {
10115       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10116       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10117         continue ;
10118       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10119       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10120     }
10121   return presenceOfOn;
10122 }
10123
10124 /// @endcond
10125
10126 /**
10127  * 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.
10128  * 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.
10129  * 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.
10130  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10131  *
10132  * \return int - the number of new nodes created (in most of cases 0).
10133  * 
10134  * \throw If \a this is not coherent.
10135  * \throw If \a this has not spaceDim equal to 2.
10136  * \throw If \a this has not meshDim equal to 2.
10137  * \throw If some subcells needed to be split are orphan.
10138  * \sa MEDCouplingUMesh::conformize2D
10139  */
10140 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10141 {
10142   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10143     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10144   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10145   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10146     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10147   if(midOpt==0 && midOptI==0)
10148     {
10149       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10150       return 0;
10151     }
10152   else if(midOpt!=0 && midOptI!=0)
10153     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10154   else
10155     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10156 }
10157
10158 /*!
10159  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10160  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10161  * 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
10162  * 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).
10163  * 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.
10164  * 
10165  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10166  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10167  *
10168  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10169  * This method expects that all nodes in \a this are not closer than \a eps.
10170  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10171  * 
10172  * \param [in] eps the relative error to detect merged edges.
10173  * \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
10174  *                           that the user is expected to deal with.
10175  *
10176  * \throw If \a this is not coherent.
10177  * \throw If \a this has not spaceDim equal to 2.
10178  * \throw If \a this has not meshDim equal to 2.
10179  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10180  */
10181 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10182 {
10183   static const int SPACEDIM=2;
10184   checkCoherency();
10185   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10186     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10188   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10189   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10190   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10191   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10192   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10193   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10194   std::vector<double> addCoo;
10195   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10196   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10197   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10198   for(int i=0;i<nDescCell;i++)
10199     {
10200       std::vector<int> candidates;
10201       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10202       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10203         if(*it>i)
10204           {
10205             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10206             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10207                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10208             INTERP_KERNEL::MergePoints merge;
10209             INTERP_KERNEL::QuadraticPolygon c1,c2;
10210             e1->intersectWith(e2,merge,c1,c2);
10211             e1->decrRef(); e2->decrRef();
10212             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10213               overlapEdge[i].push_back(*it);
10214             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10215               overlapEdge[*it].push_back(i);
10216           }
10217     }
10218   // splitting done. sort intersect point in intersectEdge.
10219   std::vector< std::vector<int> > middle(nDescCell);
10220   int nbOf2DCellsToBeSplit(0);
10221   bool middleNeedsToBeUsed(false);
10222   std::vector<bool> cells2DToTreat(nDescCell,false);
10223   for(int i=0;i<nDescCell;i++)
10224     {
10225       std::vector<int>& isect(intersectEdge[i]);
10226       int sz((int)isect.size());
10227       if(sz>1)
10228         {
10229           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10230           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10231           e->sortSubNodesAbs(coords,isect);
10232           e->decrRef();
10233         }
10234       if(sz!=0)
10235         {
10236           int idx0(rdi[i]),idx1(rdi[i+1]);
10237           if(idx1-idx0!=1)
10238             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10239           if(!cells2DToTreat[rd[idx0]])
10240             {
10241               cells2DToTreat[rd[idx0]]=true;
10242               nbOf2DCellsToBeSplit++;
10243             }
10244           // try to reuse at most eventual 'middle' of SEG3
10245           std::vector<int>& mid(middle[i]);
10246           mid.resize(sz+1,-1);
10247           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10248             {
10249               middleNeedsToBeUsed=true;
10250               const std::vector<int>& candidates(overlapEdge[i]);
10251               std::vector<int> trueCandidates;
10252               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10253                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10254                   trueCandidates.push_back(*itc);
10255               int stNode(c[ci[i]+1]),endNode(isect[0]);
10256               for(int j=0;j<sz+1;j++)
10257                 {
10258                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10259                     {
10260                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10261                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10262                         { mid[j]=*itc; break; }
10263                     }
10264                   stNode=endNode;
10265                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10266                 }
10267             }
10268         }
10269     }
10270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10271   if(nbOf2DCellsToBeSplit==0)
10272     return ret.retn();
10273   //
10274   int *retPtr(ret->getPointer());
10275   for(int i=0;i<nCell;i++)
10276     if(cells2DToTreat[i])
10277       *retPtr++=i;
10278   //
10279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10280   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10281   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10282   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10283   if(middleNeedsToBeUsed)
10284     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10285   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10286   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10287   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.
10288   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10289   {
10290     bool areNodesMerged; int newNbOfNodes;
10291     if(nbOfNodesCreated!=0)
10292       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10293   }
10294   return ret.retn();
10295 }
10296
10297 /*!
10298  * 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.
10299  * 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).
10300  * 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
10301  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10302  * 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
10303  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10304  *
10305  * 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
10306  * using new instance, idem for coordinates.
10307  *
10308  * 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.
10309  * 
10310  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10311  *
10312  * \throw If \a this is not coherent.
10313  * \throw If \a this has not spaceDim equal to 2.
10314  * \throw If \a this has not meshDim equal to 2.
10315  * 
10316  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10317  */
10318 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10319 {
10320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10321   checkCoherency();
10322   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10324   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10325   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10326   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10327   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10329   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10330   const double *coords(_coords->begin());
10331   int *newciptr(newci->getPointer());
10332   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10333     {
10334       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10335         ret->pushBackSilent(i);
10336       newciptr[1]=newc->getNumberOfTuples();
10337     }
10338   //
10339   if(ret->empty())
10340     return ret.retn();
10341   if(!appendedCoords->empty())
10342     {
10343       appendedCoords->rearrange(2);
10344       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10345       //non const part
10346       setCoords(newCoords);
10347     }
10348   //non const part
10349   setConnectivity(newc,newci,true);
10350   return ret.retn();
10351 }
10352
10353 /*!
10354  * \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.
10355  *                               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.
10356  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10357  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10358  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10359  * \param [out] addCoo - nodes to be append at the end
10360  * \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.
10361  */
10362 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10363                                          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)
10364 {
10365   static const int SPACEDIM=2;
10366   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10367   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10368   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10369   // Build BB tree of all edges in the tool mesh (second mesh)
10370   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10371   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10372   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10373   intersectEdge1.resize(nDescCell1);
10374   colinear2.resize(nDescCell2);
10375   subDiv2.resize(nDescCell2);
10376   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10377
10378   std::vector<int> candidates1(1);
10379   int offset1(m1Desc->getNumberOfNodes());
10380   int offset2(offset1+m2Desc->getNumberOfNodes());
10381   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10382     {
10383       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10384       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10385       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10386         {
10387           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10388           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10389           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10390           candidates1[0]=i;
10391           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10392           // 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
10393           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10394           std::set<INTERP_KERNEL::Node *> nodes;
10395           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10396           std::size_t szz(nodes.size());
10397           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10398           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10399           for(std::size_t iii=0;iii<szz;iii++,itt++)
10400             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10401           // end of protection
10402           // Performs egde cutting:
10403           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10404           delete pol2;
10405           delete pol1;
10406         }
10407       else
10408         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10409         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10410     }
10411 }
10412
10413 /*!
10414  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10415  * It builds the descending connectivity of the two meshes, and then using a binary tree
10416  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10417  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10418  */
10419 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10420                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10421                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10422                                                    std::vector<double>& addCoo,
10423                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10424 {
10425   // Build desc connectivity
10426   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10427   desc2=DataArrayInt::New();
10428   descIndx2=DataArrayInt::New();
10429   revDesc2=DataArrayInt::New();
10430   revDescIndx2=DataArrayInt::New();
10431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10433   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10434   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10435   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10436   std::map<int,int> notUsedMap;
10437   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10438   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10439   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10440 }
10441
10442 /*!
10443  * This method performs the 2nd step of Partition of 2D mesh.
10444  * This method has 4 inputs :
10445  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10446  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10447  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10448  * 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'
10449  * Nodes end up lying consecutively on a cutted edge.
10450  * \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.
10451  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10452  * \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.
10453  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10454  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10455  */
10456 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10457                                            const std::vector<double>& addCoo,
10458                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10459 {
10460   int offset1=m1->getNumberOfNodes();
10461   int ncell=m2->getNumberOfCells();
10462   const int *c=m2->getNodalConnectivity()->getConstPointer();
10463   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10464   const double *coo=m2->getCoords()->getConstPointer();
10465   const double *cooBis=m1->getCoords()->getConstPointer();
10466   int offset2=offset1+m2->getNumberOfNodes();
10467   intersectEdge.resize(ncell);
10468   for(int i=0;i<ncell;i++,cI++)
10469     {
10470       const std::vector<int>& divs=subDiv[i];
10471       int nnode=cI[1]-cI[0]-1;
10472       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10473       std::map<INTERP_KERNEL::Node *, int> mapp22;
10474       for(int j=0;j<nnode;j++)
10475         {
10476           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10477           int nnid=c[(*cI)+j+1];
10478           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10479           mapp22[nn]=nnid+offset1;
10480         }
10481       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10482       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10483         ((*it).second.first)->decrRef();
10484       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10485       std::map<INTERP_KERNEL::Node *,int> mapp3;
10486       for(std::size_t j=0;j<divs.size();j++)
10487         {
10488           int id=divs[j];
10489           INTERP_KERNEL::Node *tmp=0;
10490           if(id<offset1)
10491             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10492           else if(id<offset2)
10493             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10494           else
10495             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10496           addNodes[j]=tmp;
10497           mapp3[tmp]=id;
10498         }
10499       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10500       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10501         (*it)->decrRef();
10502       e->decrRef();
10503     }
10504 }
10505
10506 /*!
10507  * 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).
10508  * 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
10509  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10510  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10511  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10512  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10513  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10514  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10515  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10516  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10517  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10518  * \param [out] cut3DSuf input/output param.
10519  */
10520 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10521                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10522                                                    const int *desc, const int *descIndx, 
10523                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10524 {
10525   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10526   int nbOf3DSurfCell=(int)cut3DSurf.size();
10527   for(int i=0;i<nbOf3DSurfCell;i++)
10528     {
10529       std::vector<int> res;
10530       int offset=descIndx[i];
10531       int nbOfSeg=descIndx[i+1]-offset;
10532       for(int j=0;j<nbOfSeg;j++)
10533         {
10534           int edgeId=desc[offset+j];
10535           int status=cut3DCurve[edgeId];
10536           if(status!=-2)
10537             {
10538               if(status>-1)
10539                 res.push_back(status);
10540               else
10541                 {
10542                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10543                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10544                 }
10545             }
10546         }
10547       switch(res.size())
10548       {
10549         case 2:
10550           {
10551             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10552             break;
10553           }
10554         case 1:
10555         case 0:
10556           {
10557             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10558             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10559             if(res.size()==2)
10560               {
10561                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10562               }
10563             else
10564               {
10565                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10566               }
10567             break;
10568           }
10569         default:
10570           {// case when plane is on a multi colinear edge of a polyhedron
10571             if((int)res.size()==2*nbOfSeg)
10572               {
10573                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10574               }
10575             else
10576               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10577           }
10578       }
10579     }
10580 }
10581
10582 /*!
10583  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10584  * 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).
10585  * 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
10586  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10587  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10588  * \param desc is the descending connectivity 3D->3DSurf
10589  * \param descIndx is the descending connectivity index 3D->3DSurf
10590  */
10591 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10592                                                   const int *desc, const int *descIndx,
10593                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10594 {
10595   checkFullyDefined();
10596   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10597     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10598   const int *nodal3D=_nodal_connec->getConstPointer();
10599   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10600   int nbOfCells=getNumberOfCells();
10601   for(int i=0;i<nbOfCells;i++)
10602     {
10603       std::map<int, std::set<int> > m;
10604       int offset=descIndx[i];
10605       int nbOfFaces=descIndx[i+1]-offset;
10606       int start=-1;
10607       int end=-1;
10608       for(int j=0;j<nbOfFaces;j++)
10609         {
10610           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10611           if(p.first!=-1 && p.second!=-1)
10612             {
10613               if(p.first!=-2)
10614                 {
10615                   start=p.first; end=p.second;
10616                   m[p.first].insert(p.second);
10617                   m[p.second].insert(p.first);
10618                 }
10619               else
10620                 {
10621                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10622                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10623                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10624                   INTERP_KERNEL::NormalizedCellType cmsId;
10625                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10626                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10627                   for(unsigned k=0;k<nbOfNodesSon;k++)
10628                     {
10629                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10630                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10631                     }
10632                 }
10633             }
10634         }
10635       if(m.empty())
10636         continue;
10637       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10638       int prev=end;
10639       while(end!=start)
10640         {
10641           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10642           const std::set<int>& s=(*it).second;
10643           std::set<int> s2; s2.insert(prev);
10644           std::set<int> s3;
10645           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10646           if(s3.size()==1)
10647             {
10648               int val=*s3.begin();
10649               conn.push_back(start);
10650               prev=start;
10651               start=val;
10652             }
10653           else
10654             start=end;
10655         }
10656       conn.push_back(end);
10657       if(conn.size()>3)
10658         {
10659           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10660           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10661           cellIds->pushBackSilent(i);
10662         }
10663     }
10664 }
10665
10666 /*!
10667  * 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
10668  * 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
10669  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10670  * 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
10671  * 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.
10672  * 
10673  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10674  */
10675 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10676 {
10677   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10678   if(sz>=4)
10679     {
10680       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10681       if(cm.getDimension()==2)
10682         {
10683           const int *node=nodalConnBg+1;
10684           int startNode=*node++;
10685           double refX=coords[2*startNode];
10686           for(;node!=nodalConnEnd;node++)
10687             {
10688               if(coords[2*(*node)]<refX)
10689                 {
10690                   startNode=*node;
10691                   refX=coords[2*startNode];
10692                 }
10693             }
10694           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10695           refX=1e300;
10696           double tmp1;
10697           double tmp2[2];
10698           double angle0=-M_PI/2;
10699           //
10700           int nextNode=-1;
10701           int prevNode=-1;
10702           double resRef;
10703           double angleNext=0.;
10704           while(nextNode!=startNode)
10705             {
10706               nextNode=-1;
10707               resRef=1e300;
10708               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10709                 {
10710                   if(*node!=tmpOut.back() && *node!=prevNode)
10711                     {
10712                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10713                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10714                       double res;
10715                       if(angleM<=angle0)
10716                         res=angle0-angleM;
10717                       else
10718                         res=angle0-angleM+2.*M_PI;
10719                       if(res<resRef)
10720                         {
10721                           nextNode=*node;
10722                           resRef=res;
10723                           angleNext=angleM;
10724                         }
10725                     }
10726                 }
10727               if(nextNode!=startNode)
10728                 {
10729                   angle0=angleNext-M_PI;
10730                   if(angle0<-M_PI)
10731                     angle0+=2*M_PI;
10732                   prevNode=tmpOut.back();
10733                   tmpOut.push_back(nextNode);
10734                 }
10735             }
10736           std::vector<int> tmp3(2*(sz-1));
10737           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10738           std::copy(nodalConnBg+1,nodalConnEnd,it);
10739           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10740             {
10741               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10742               return false;
10743             }
10744           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10745             {
10746               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10747               return false;
10748             }
10749           else
10750             {
10751               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10752               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10753               return true;
10754             }
10755         }
10756       else
10757         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10758     }
10759   else
10760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10761 }
10762
10763 /*!
10764  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10765  * 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.
10766  * 
10767  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10768  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10769  * \param [in,out] arr array in which the remove operation will be done.
10770  * \param [in,out] arrIndx array in the remove operation will modify
10771  * \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])
10772  * \return true if \b arr and \b arrIndx have been modified, false if not.
10773  */
10774 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10775 {
10776   if(!arrIndx || !arr)
10777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10778   if(offsetForRemoval<0)
10779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10780   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10781   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10782   int *arrIPtr=arrIndx->getPointer();
10783   *arrIPtr++=0;
10784   int previousArrI=0;
10785   const int *arrPtr=arr->getConstPointer();
10786   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10787   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10788     {
10789       if(*arrIPtr-previousArrI>offsetForRemoval)
10790         {
10791           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10792             {
10793               if(s.find(*work)==s.end())
10794                 arrOut.push_back(*work);
10795             }
10796         }
10797       previousArrI=*arrIPtr;
10798       *arrIPtr=(int)arrOut.size();
10799     }
10800   if(arr->getNumberOfTuples()==(int)arrOut.size())
10801     return false;
10802   arr->alloc((int)arrOut.size(),1);
10803   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10804   return true;
10805 }
10806
10807 /*!
10808  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10809  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10810  * The selection of extraction is done standardly in new2old format.
10811  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10812  *
10813  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10814  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10815  * \param [in] arrIn arr origin array from which the extraction will be done.
10816  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10817  * \param [out] arrOut the resulting array
10818  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10819  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10820  */
10821 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10822                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10823 {
10824   if(!arrIn || !arrIndxIn)
10825     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10826   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10827   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10828     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10829   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10830   const int *arrInPtr=arrIn->getConstPointer();
10831   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10832   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10833   if(nbOfGrps<0)
10834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10835   int maxSizeOfArr=arrIn->getNumberOfTuples();
10836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10838   arrIo->alloc((int)(sz+1),1);
10839   const int *idsIt=idsOfSelectBg;
10840   int *work=arrIo->getPointer();
10841   *work++=0;
10842   int lgth=0;
10843   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10844     {
10845       if(*idsIt>=0 && *idsIt<nbOfGrps)
10846         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10847       else
10848         {
10849           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10850           throw INTERP_KERNEL::Exception(oss.str().c_str());
10851         }
10852       if(lgth>=work[-1])
10853         *work=lgth;
10854       else
10855         {
10856           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10857           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10858           throw INTERP_KERNEL::Exception(oss.str().c_str());
10859         }
10860     }
10861   arro->alloc(lgth,1);
10862   work=arro->getPointer();
10863   idsIt=idsOfSelectBg;
10864   for(std::size_t i=0;i<sz;i++,idsIt++)
10865     {
10866       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10867         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10868       else
10869         {
10870           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10871           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10872           throw INTERP_KERNEL::Exception(oss.str().c_str());
10873         }
10874     }
10875   arrOut=arro.retn();
10876   arrIndexOut=arrIo.retn();
10877 }
10878
10879 /*!
10880  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10881  * 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 ).
10882  * The selection of extraction is done standardly in new2old format.
10883  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10884  *
10885  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10886  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10887  * \param [in] arrIn arr origin array from which the extraction will be done.
10888  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10889  * \param [out] arrOut the resulting array
10890  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10891  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10892  */
10893 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10894                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10895 {
10896   if(!arrIn || !arrIndxIn)
10897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10898   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10899   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10900     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10901   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10902   const int *arrInPtr=arrIn->getConstPointer();
10903   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10904   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10905   if(nbOfGrps<0)
10906     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10907   int maxSizeOfArr=arrIn->getNumberOfTuples();
10908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10909   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10910   arrIo->alloc((int)(sz+1),1);
10911   int idsIt=idsOfSelectStart;
10912   int *work=arrIo->getPointer();
10913   *work++=0;
10914   int lgth=0;
10915   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10916     {
10917       if(idsIt>=0 && idsIt<nbOfGrps)
10918         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10919       else
10920         {
10921           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10922           throw INTERP_KERNEL::Exception(oss.str().c_str());
10923         }
10924       if(lgth>=work[-1])
10925         *work=lgth;
10926       else
10927         {
10928           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10929           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10930           throw INTERP_KERNEL::Exception(oss.str().c_str());
10931         }
10932     }
10933   arro->alloc(lgth,1);
10934   work=arro->getPointer();
10935   idsIt=idsOfSelectStart;
10936   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10937     {
10938       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10939         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10940       else
10941         {
10942           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10943           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10944           throw INTERP_KERNEL::Exception(oss.str().c_str());
10945         }
10946     }
10947   arrOut=arro.retn();
10948   arrIndexOut=arrIo.retn();
10949 }
10950
10951 /*!
10952  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10953  * 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
10954  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10955  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10956  *
10957  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10958  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10959  * \param [in] arrIn arr origin array from which the extraction will be done.
10960  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10961  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10962  * \param [in] srcArrIndex index array of \b srcArr
10963  * \param [out] arrOut the resulting array
10964  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10965  * 
10966  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10967  */
10968 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10969                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10970                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10971 {
10972   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10973     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10976   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10977   std::vector<bool> v(nbOfTuples,true);
10978   int offset=0;
10979   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10980   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10981   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10982     {
10983       if(*it>=0 && *it<nbOfTuples)
10984         {
10985           v[*it]=false;
10986           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10987         }
10988       else
10989         {
10990           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10991           throw INTERP_KERNEL::Exception(oss.str().c_str());
10992         }
10993     }
10994   srcArrIndexPtr=srcArrIndex->getConstPointer();
10995   arrIo->alloc(nbOfTuples+1,1);
10996   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10997   const int *arrInPtr=arrIn->getConstPointer();
10998   const int *srcArrPtr=srcArr->getConstPointer();
10999   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11000   int *arroPtr=arro->getPointer();
11001   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11002     {
11003       if(v[ii])
11004         {
11005           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11006           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11007         }
11008       else
11009         {
11010           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11011           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11012           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11013         }
11014     }
11015   arrOut=arro.retn();
11016   arrIndexOut=arrIo.retn();
11017 }
11018
11019 /*!
11020  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11021  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11022  *
11023  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11024  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11025  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11026  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11027  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11028  * \param [in] srcArrIndex index array of \b srcArr
11029  * 
11030  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11031  */
11032 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11033                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11034 {
11035   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11036     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11037   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11038   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11039   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11040   int *arrInOutPtr=arrInOut->getPointer();
11041   const int *srcArrPtr=srcArr->getConstPointer();
11042   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11043     {
11044       if(*it>=0 && *it<nbOfTuples)
11045         {
11046           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11047             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11048           else
11049             {
11050               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] !";
11051               throw INTERP_KERNEL::Exception(oss.str().c_str());
11052             }
11053         }
11054       else
11055         {
11056           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11057           throw INTERP_KERNEL::Exception(oss.str().c_str());
11058         }
11059     }
11060 }
11061
11062 /*!
11063  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11064  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11065  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11066  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11067  * A negative value in \b arrIn means that it is ignored.
11068  * 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.
11069  * 
11070  * \param [in] arrIn arr origin array from which the extraction will be done.
11071  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11072  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11073  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11074  */
11075 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11076 {
11077   int seed=0,nbOfDepthPeelingPerformed=0;
11078   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11079 }
11080
11081 /*!
11082  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11083  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11084  * 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]].
11085  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11086  * A negative value in \b arrIn means that it is ignored.
11087  * 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.
11088  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11089  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11090  * \param [in] arrIn arr origin array from which the extraction will be done.
11091  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11092  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11093  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11094  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11095  * \sa MEDCouplingUMesh::partitionBySpreadZone
11096  */
11097 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11098 {
11099   nbOfDepthPeelingPerformed=0;
11100   if(!arrIndxIn)
11101     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11102   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11103   if(nbOfTuples<=0)
11104     {
11105       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11106       return ret;
11107     }
11108   //
11109   std::vector<bool> fetched(nbOfTuples,false);
11110   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11111 }
11112
11113 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11114 {
11115   nbOfDepthPeelingPerformed=0;
11116   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11117     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11118   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11119   std::vector<bool> fetched2(nbOfTuples,false);
11120   int i=0;
11121   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11122     {
11123       if(*seedElt>=0 && *seedElt<nbOfTuples)
11124         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11125       else
11126         { 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()); }
11127     }
11128   const int *arrInPtr=arrIn->getConstPointer();
11129   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11130   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11131   std::vector<int> idsToFetch1(seedBg,seedEnd);
11132   std::vector<int> idsToFetch2;
11133   std::vector<int> *idsToFetch=&idsToFetch1;
11134   std::vector<int> *idsToFetchOther=&idsToFetch2;
11135   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11136     {
11137       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11138         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11139           if(!fetched[*it2])
11140             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11141       std::swap(idsToFetch,idsToFetchOther);
11142       idsToFetchOther->clear();
11143       nbOfDepthPeelingPerformed++;
11144     }
11145   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11146   i=0;
11147   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11148   int *retPtr=ret->getPointer();
11149   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11150     if(*it)
11151       *retPtr++=i;
11152   return ret.retn();
11153 }
11154
11155 /*!
11156  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11157  * 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
11158  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11159  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11160  *
11161  * \param [in] start begin of set of ids of the input extraction (included)
11162  * \param [in] end end of set of ids of the input extraction (excluded)
11163  * \param [in] step step of the set of ids in range mode.
11164  * \param [in] arrIn arr origin array from which the extraction will be done.
11165  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11166  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11167  * \param [in] srcArrIndex index array of \b srcArr
11168  * \param [out] arrOut the resulting array
11169  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11170  * 
11171  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11172  */
11173 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11174                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11175                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11176 {
11177   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11178     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11181   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11182   int offset=0;
11183   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11184   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11185   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11186   int it=start;
11187   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11188     {
11189       if(it>=0 && it<nbOfTuples)
11190         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11191       else
11192         {
11193           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11194           throw INTERP_KERNEL::Exception(oss.str().c_str());
11195         }
11196     }
11197   srcArrIndexPtr=srcArrIndex->getConstPointer();
11198   arrIo->alloc(nbOfTuples+1,1);
11199   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11200   const int *arrInPtr=arrIn->getConstPointer();
11201   const int *srcArrPtr=srcArr->getConstPointer();
11202   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11203   int *arroPtr=arro->getPointer();
11204   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11205     {
11206       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11207       if(pos<0)
11208         {
11209           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11210           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11211         }
11212       else
11213         {
11214           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11215           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11216         }
11217     }
11218   arrOut=arro.retn();
11219   arrIndexOut=arrIo.retn();
11220 }
11221
11222 /*!
11223  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11224  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11225  *
11226  * \param [in] start begin of set of ids of the input extraction (included)
11227  * \param [in] end end of set of ids of the input extraction (excluded)
11228  * \param [in] step step of the set of ids in range mode.
11229  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11230  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11231  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11232  * \param [in] srcArrIndex index array of \b srcArr
11233  * 
11234  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11235  */
11236 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11237                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11238 {
11239   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11240     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11241   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11242   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11243   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11244   int *arrInOutPtr=arrInOut->getPointer();
11245   const int *srcArrPtr=srcArr->getConstPointer();
11246   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11247   int it=start;
11248   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11249     {
11250       if(it>=0 && it<nbOfTuples)
11251         {
11252           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11253             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11254           else
11255             {
11256               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11257               throw INTERP_KERNEL::Exception(oss.str().c_str());
11258             }
11259         }
11260       else
11261         {
11262           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11263           throw INTERP_KERNEL::Exception(oss.str().c_str());
11264         }
11265     }
11266 }
11267
11268 /*!
11269  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11270  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11271  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11272  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11273  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11274  * 
11275  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11276  */
11277 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11278 {
11279   checkFullyDefined();
11280   int mdim=getMeshDimension();
11281   int spaceDim=getSpaceDimension();
11282   if(mdim!=spaceDim)
11283     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11284   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11285   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11286   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11287   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11288   ret->setCoords(getCoords());
11289   ret->allocateCells((int)partition.size());
11290   //
11291   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11292     {
11293       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11294       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11295       switch(mdim)
11296       {
11297         case 2:
11298           cell=tmp->buildUnionOf2DMesh();
11299           break;
11300         case 3:
11301           cell=tmp->buildUnionOf3DMesh();
11302           break;
11303         default:
11304           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11305       }
11306
11307       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11308     }
11309   //
11310   ret->finishInsertingCells();
11311   return ret.retn();
11312 }
11313
11314 /*!
11315  * This method partitions \b this into contiguous zone.
11316  * This method only needs a well defined connectivity. Coordinates are not considered here.
11317  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11318  */
11319 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11320 {
11321   int nbOfCellsCur=getNumberOfCells();
11322   std::vector<DataArrayInt *> ret;
11323   if(nbOfCellsCur<=0)
11324     return ret;
11325   DataArrayInt *neigh=0,*neighI=0;
11326   computeNeighborsOfCells(neigh,neighI);
11327   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11328   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11329   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11330   int seed=0;
11331   while(seed<nbOfCellsCur)
11332     {
11333       int nbOfPeelPerformed=0;
11334       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11335       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11336     }
11337   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11338     ret.push_back((*it).retn());
11339   return ret;
11340 }
11341
11342 /*!
11343  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11344  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11345  *
11346  * \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.
11347  * \return a newly allocated DataArrayInt to be managed by the caller.
11348  * \throw In case of \a code has not the right format (typically of size 3*n)
11349  */
11350 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11351 {
11352   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11353   std::size_t nb=code.size()/3;
11354   if(code.size()%3!=0)
11355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11356   ret->alloc((int)nb,2);
11357   int *retPtr=ret->getPointer();
11358   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11359     {
11360       retPtr[0]=code[3*i+2];
11361       retPtr[1]=code[3*i+2]+code[3*i+1];
11362     }
11363   return ret.retn();
11364 }
11365
11366 /*!
11367  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11368  * All cells in \a this are expected to be linear 3D cells.
11369  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11370  * It leads to an increase to number of cells.
11371  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11372  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11373  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11374  *
11375  * \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.
11376  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11377  * \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. 
11378  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11379  *          an id of old cell producing it. The caller is to delete this array using
11380  *         decrRef() as it is no more needed.
11381  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11382  *
11383  * \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
11384  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11385  * 
11386  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11387  * \throw If \a this is not fully constituted with linear 3D cells.
11388  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11389  */
11390 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11391 {
11392   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11393   checkConnectivityFullyDefined();
11394   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11396   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11397   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11399   int *retPt(ret->getPointer());
11400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11401   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11402   const int *oldc(_nodal_connec->begin());
11403   const int *oldci(_nodal_connec_index->begin());
11404   const double *coords(_coords->begin());
11405   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11406     {
11407       std::vector<int> a; std::vector<double> b;
11408       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11409       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11410       const int *aa(&a[0]);
11411       if(!b.empty())
11412         {
11413           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11414             if(*it<0)
11415               *it=(-(*(it))-1+nbNodes);
11416           addPts->insertAtTheEnd(b.begin(),b.end());
11417           nbNodes+=(int)b.size()/3;
11418         }
11419       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11420         newConn->insertAtTheEnd(aa,aa+4);
11421     }
11422   if(!addPts->empty())
11423     {
11424       addPts->rearrange(3);
11425       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11426       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11427       ret0->setCoords(addPts);
11428     }
11429   else
11430     {
11431       nbOfAdditionalPoints=0;
11432       ret0->setCoords(getCoords());
11433     }
11434   ret0->setNodalConnectivity(newConn);
11435   //
11436   ret->computeOffsets2();
11437   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11438   return ret0.retn();
11439 }
11440
11441 /*!
11442  * 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). 
11443  *
11444  * \sa MEDCouplingUMesh::split2DCells
11445  */
11446 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11447 {
11448   checkConnectivityFullyDefined();
11449   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11451   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11452   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11453   int prevPosOfCi(ciPtr[0]);
11454   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11455     {
11456       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11457       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11458       for(int j=0;j<sz;j++)
11459         {
11460           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11461           for(int k=0;k<sz2;k++)
11462             *cPtr++=subPtr[offset2+k];
11463           if(j!=sz-1)
11464             *cPtr++=oldConn[prevPosOfCi+j+2];
11465           deltaSz+=sz2;
11466         }
11467       prevPosOfCi=ciPtr[1];
11468       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11469     }
11470   if(c->end()!=cPtr)
11471     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11472   _nodal_connec->decrRef();
11473   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11474 }
11475
11476 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11477 {
11478   if(id!=-1)
11479     return id;
11480   else
11481     {
11482       int ret(nodesCnter++);
11483       double newPt[2];
11484       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11485       addCoo.insertAtTheEnd(newPt,newPt+2);
11486       return ret;
11487     }
11488 }
11489
11490 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11491 {
11492   if(id!=-1)
11493     return id;
11494   else
11495     {
11496       int ret(nodesCnter++);
11497       double newPt[2];
11498       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11499       addCoo.insertAtTheEnd(newPt,newPt+2);
11500       return ret;
11501     }
11502 }
11503
11504
11505 /// @cond INTERNAL
11506
11507 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)
11508 {
11509   int tmp[3];
11510   int trueStart(start>=0?start:nbOfEdges+start);
11511   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11512   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11513   if(linOrArc)
11514     {
11515       if(stp-start>1)
11516         {
11517           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11518           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11519           middles.push_back(tmp3+offset);
11520         }
11521       else
11522         middles.push_back(connBg[trueStart+nbOfEdges]);
11523     }
11524 }
11525
11526 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)
11527 {
11528   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11529   newConnOfCell->pushBackSilent(tmpEnd);
11530   if(linOrArc)
11531     {
11532       if(stp-start>1)
11533         {
11534           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11535           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11536           middles.push_back(tmp3+offset);
11537         }
11538       else
11539         middles.push_back(connBg[start+nbOfEdges]);
11540     }
11541 }
11542
11543 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)
11544 {
11545   // only the quadratic point to deal with:
11546   if(linOrArc)
11547     {
11548       if(stp-start>1)
11549         {
11550           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11551           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11552           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11553           middles.push_back(tmp3+offset);
11554         }
11555       else
11556         middles.push_back(connBg[start+nbOfEdges]);
11557     }
11558 }
11559
11560 /// @cond INTERNAL
11561
11562 /*!
11563  * 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 ) .
11564  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11565  */
11566 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11567 {
11568   std::size_t sz(std::distance(connBg,connEnd));
11569   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11570     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11571   sz--;
11572   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11573   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11574   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11575   unsigned nbOfHit(0); // number of fusions operated
11576   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11577   const unsigned int maxNbOfHit = cm.isQuadratic() ? nbs-2 : nbs-3;  // a quad cell is authorized to end up with only two edges, a linear one has to keep 3 at least
11578   INTERP_KERNEL::NormalizedCellType typeOfSon;
11579   std::vector<int> middles;
11580   bool ret(false);
11581   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11582     {
11583       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11584       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11585       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11586       posEndElt = posBaseElt+1;
11587
11588       // Look backward first: are the final edges of the cells colinear with the first ones?
11589       // This initializes posBaseElt.
11590       if(nbOfTurn==0)
11591         {
11592           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11593             {
11594               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11595               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11596               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11597               bool isColinear=eint->areColinears();
11598               if(isColinear)
11599                 {
11600                   nbOfHit++;
11601                   posBaseElt--;
11602                   ret=true;
11603                 }
11604               delete eint;
11605               eCand->decrRef();
11606               if(!isColinear)
11607                 break;
11608             }
11609         }
11610       // Now move forward:
11611       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11612       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11613         {
11614           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11615           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11616           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11617           bool isColinear(eint->areColinears());
11618           if(isColinear)
11619             {
11620               nbOfHit++;
11621               posEndElt++;
11622               ret=true;
11623             }
11624           delete eint;
11625           eCand->decrRef();
11626           if(!isColinear)
11627               break;
11628         }
11629       //push [posBaseElt,posEndElt) in newConnOfCell using e
11630       // The if clauses below are (volontary) not mutually exclusive: on a quad cell with 2 edges, the end of the connectivity is also its begining!
11631       if(nbOfTurn==0)
11632         // at the begining of the connectivity (insert type)
11633         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11634       else if((nbOfHit+nbOfTurn) != (nbs-1))
11635         // in the middle
11636         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11637       if ((nbOfHit+nbOfTurn) == (nbs-1))
11638         // at the end (only quad points to deal with)
11639         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11640       posBaseElt=posEndElt;
11641       e->decrRef();
11642     }
11643   if(!middles.empty())
11644     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11645   return ret;
11646 }
11647
11648 /*!
11649  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11650  *
11651  * \return  int - the number of new nodes created.
11652  * \sa MEDCouplingUMesh::split2DCells
11653  */
11654 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11655 {
11656   checkCoherency();
11657   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11659   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11660   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11661   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11662   const double *oldCoordsPtr(getCoords()->begin());
11663   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11664   int prevPosOfCi(ciPtr[0]);
11665   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11666     {
11667       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11668       for(int j=0;j<sz;j++)
11669         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11670       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11671       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11672         {
11673           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11674           if(sz2==0)
11675             {
11676               if(j<sz-1)
11677                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11678               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11679               continue;
11680             }
11681           std::vector<INTERP_KERNEL::Node *> ns(3);
11682           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11683           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11684           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11685           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11686           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11687             {
11688               cPtr[1]=subPtr[offset2+k];
11689               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11690             }
11691           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11692           if(j!=sz-1)
11693             { cPtr[1]=tmpEnd; }
11694           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11695         }
11696       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11697       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11698     }
11699   if(c->end()!=cPtr)
11700     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11701   _nodal_connec->decrRef();
11702   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11703   addCoo->rearrange(2);
11704   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11705   setCoords(coo);
11706   return addCoo->getNumberOfTuples();
11707 }
11708
11709 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11710 {
11711   if(nodalConnec && nodalConnecIndex)
11712     {
11713       types.clear();
11714       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11715       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11716       if(nbOfElem>0)
11717         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11718           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11719     }
11720 }
11721
11722 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11723     _own_cell(true),_cell_id(-1),_nb_cell(0)
11724 {
11725   if(mesh)
11726     {
11727       mesh->incrRef();
11728       _nb_cell=mesh->getNumberOfCells();
11729     }
11730 }
11731
11732 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11733 {
11734   if(_mesh)
11735     _mesh->decrRef();
11736   if(_own_cell)
11737     delete _cell;
11738 }
11739
11740 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11741     _own_cell(false),_cell_id(bg-1),
11742     _nb_cell(end)
11743 {
11744   if(mesh)
11745     mesh->incrRef();
11746 }
11747
11748 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11749 {
11750   _cell_id++;
11751   if(_cell_id<_nb_cell)
11752     {
11753       _cell->next();
11754       return _cell;
11755     }
11756   else
11757     return 0;
11758 }
11759
11760 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11761 {
11762   if(_mesh)
11763     _mesh->incrRef();
11764 }
11765
11766 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11767 {
11768   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11769 }
11770
11771 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11772 {
11773   if(_mesh)
11774     _mesh->decrRef();
11775 }
11776
11777 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11778     _itc(itc),
11779     _bg(bg),_end(end)
11780 {
11781   if(_mesh)
11782     _mesh->incrRef();
11783 }
11784
11785 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11786 {
11787   if(_mesh)
11788     _mesh->decrRef();
11789 }
11790
11791 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11792 {
11793   return _type;
11794 }
11795
11796 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11797 {
11798   return _end-_bg;
11799 }
11800
11801 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11802 {
11803   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11804 }
11805
11806 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11807 {
11808   if(mesh)
11809     {
11810       mesh->incrRef();
11811       _nb_cell=mesh->getNumberOfCells();
11812     }
11813 }
11814
11815 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11816 {
11817   if(_mesh)
11818     _mesh->decrRef();
11819   delete _cell;
11820 }
11821
11822 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11823 {
11824   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11825   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11826   if(_cell_id<_nb_cell)
11827     {
11828       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11829       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11830       int startId=_cell_id;
11831       _cell_id+=nbOfElems;
11832       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11833     }
11834   else
11835     return 0;
11836 }
11837
11838 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11839 {
11840   if(mesh)
11841     {
11842       _conn=mesh->getNodalConnectivity()->getPointer();
11843       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11844     }
11845 }
11846
11847 void MEDCouplingUMeshCell::next()
11848 {
11849   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11850     {
11851       _conn+=_conn_lgth;
11852       _conn_indx++;
11853     }
11854   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11855 }
11856
11857 std::string MEDCouplingUMeshCell::repr() const
11858 {
11859   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11860     {
11861       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11862       oss << " : ";
11863       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11864       return oss.str();
11865     }
11866   else
11867     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11868 }
11869
11870 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11871 {
11872   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11873     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11874   else
11875     return INTERP_KERNEL::NORM_ERROR;
11876 }
11877
11878 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11879 {
11880   lgth=_conn_lgth;
11881   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11882     return _conn;
11883   else
11884     return 0;
11885 }